Skip to content

Instantly share code, notes, and snippets.

@data-ux
Created November 20, 2018 06:53
Show Gist options
  • Save data-ux/cbd192cb353a1f764199d4f9afba181f to your computer and use it in GitHub Desktop.
Save data-ux/cbd192cb353a1f764199d4f9afba181f to your computer and use it in GitHub Desktop.
RPC apukirjasto

Motivaatio

Modernit JS-näkymäframeworkit (React, Angular, Vue, jne.) perustuvat näkymän tilan automaattiseen renderöintiin. Muutos tilassa johtaa muutokseen sivun DOM-rakenteessa siten että vain muuttuneet osat päivitetään.

Oskari-rpc taas perustuu metodikutsun omaisiin requesteihin sekä eventien seuraamiseen. Nämä kaksi mallia on hankalaa sovittaa yhteen ja jokainen sovellus joutuu toteuttamaan liimakerroksen itse.

RPC-sovellusten kehittämistä helpottaisi suuresti, jos olisi olemassa sovituskirjasto, joka auttaisi mäppäämään halutun sovelluskohtaisen kartan tilan ja oskari-rpc-kartan tilan. Ts. "one-way data-binding" oskari-rpc:lle.

oskari-rpc-mediator

Ajatuksen ydin olisi siinä että apuolio oskari-rpc-mediator hallinnoisi RPC-channelia ja pitäisi huolen siitä että jaetun Oskari-kartan sisäinen tila vastaisi sovelluksessa haluttua tilaa. Aina kun sovelluskohtainen kartan tila on muuttunut, sovellus kutsuisi mediatorin setState()-metodia tilan määrittelevällä objektilla.

Miten sovelluskohtainen tila tulkitaan oskari-kartan tilaksi?

Mediatoria luodessa annetaan sille vapaavalintainen määrä "handlereita", jotka hoitavat jonkin tilan aspektin (kuten markerit, näkyvissä olevat tasot, yms.) synkronoimisen.

Handlerin tehtävänä on pitää kirjaa oskari-kartan tilasta hoidettavan aspektin näkökulmasta ja setState:a kutsuttaessa synkronoida oskari-kartan tila vastaamaan annettua tilaobjektia. Se miten tämä tehdään on sovelluskohtaista ja märitellään handleria kirjoitettaessa.

Entä Oskarin eventit?

Handler voi kuunnella Oskarin eventejä ja käyttää tarvittaessa handlerin hallinnoimaa tilaa omassa eventiin reagoimisen logiikassa. Handler voi eventin perusteella esim. lähettää Reduxin actionin tai puhtaassa React-sovelluksessa kutsua props:ssa annettua funktiota tai tuottaa Angular-eventin.

API

Mediator-instanssi luodaan antamalla viittaus iFrameen, iFramen domain ja lista handlereita:

const mediator = new RPCMediator(iFrameElement, iFrameDomain, [
    new MarkerHandler(store),
    new VectorFeatureHandler(store),
    new MapViewHandler(store)
]);

Handler on mikä tahansa olio, jolla on metodit "init" ja "synchronize", esimerkistä yllä:

class MarkerHandler {
    constructor(store) {
        this.store = store; // Redux store
        this.markers = [];
    }
    init(channel) {
        channel.handleEvent('MapClickedEvent', (data) => {
            this.store.dispatch(/* add new marker to state tree */);
        });
    }
    synchronize(channel, state) { // state is argument of mediator.setState(...)
        // add & update
        state.markers.forEach((marker => {
            channel.postRequest('MapModulePlugin.AddMarkerRequest', [marker.payload, marker.id]);
        }));

        // delete
        const stateMarkers = new Map(state.markers.map((marker) => [marker.id, marker]));
        const toDelete = this.markers.filter((marker) => !stateMarkers.has(marker.id));
        toDelete.forEach((marker) => {
            channel.postRequest('MapModulePlugin.RemoveMarkersRequest', [marker.id]);
        });

        this.markers = state.markers;
    }
}

init() metodia kutsutaan kun kanava on valmis

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment