2014-11-26 16 views
7

non sono sicuro sul modo migliore per andare su questo:Mantenere client Stato Up-To-Date in Reattivo/ClojureScript

Ho un'applicazione web che sto scrivendo che implementa funzionalità di base CRUD per una serie di " Progetto "oggetti. Quindi, un utente può creare il proprio insieme di progetti.

Ho scritto un'API REST per aggiungere/rimuovere/elencare i progetti e ho scritto un client front-end Reagent. I progetti del cliente sono tenuti in un atomo di reagente (ratom), come ci si aspetterebbe.

Questo è il posto dove diventa interessante.

In tutte le esercitazioni che ho visto, mostra come aggiornare ratom e la GUI si aggiornerà automaticamente. Ce l'ho, funziona.

Quello che sto facendo è, al momento dell'aggiornamento dello stato del client, effettuo la mia chiamata REST POST per aggiornare lo stato del server sul database.

Ma questo non sembra giusto. Ora sto memorizzando lo stato in due punti: sul client e sul server, ed entrambi potrebbero essere diversi.

Se stavo implementando questa come una semplice pagina Web vecchia, il server invierebbe una pagina al client con lo stato più recente del database al suo interno. Ma lo stato esiste già sul client nel ratom e non so come dovrei sincronizzarlo.

Devo effettuare un'altra chiamata al server (una richiesta GET) dopo che il POST iniziale ha avuto esito positivo? Questo potrebbe sostituire il contenuto del ratom. Allora sto facendo due richieste ... che sembra uno spreco.

O è la pratica migliore per usare qualcosa come accordo o Sente per gestire lo stato del client in modo asincrono. Questo sarebbe meglio, poiché significherebbe che le modifiche da altri utenti verrebbero immediatamente aggiornate dal lato client. Ma non riesco a vedere alcun tutorial che dimostri di reagire con uno di questi, quindi forse sono sulla strada sbagliata.

Quindi la domanda è semplicemente, come si dovrebbe combinare una reazione con REST?

grazie

risposta

3

Sono d'accordo con @myguidingstar che il vostro problema è più sulla sincronizzazione client-server che su clojure o reagente. Potresti avere un problema simile, ad esempio con GWT (stato lì, ...)

Devo effettuare un'altra chiamata al server (una richiesta GET) dopo che il POST iniziale ha avuto esito positivo? Questo potrebbe sostituire il contenuto del ratom. Allora sto facendo due richieste ... che sembra uno spreco.

Sembra che manchi che le richieste POST possano anche attivare le risposte dal server.

La grande domanda qui è perché avete bisogno dello stato DB sul client? Hai dei requisiti che ti costringono a ridurre al minimo la quantità di richieste GET per recuperare i dati dal server? Oppure la logica aziendale è implementata sul lato client (ClojureScript/reagent) che non ha bisogno di interazione con il server? È necessario considerare anche l'altro aspetto dello stesso problema: va bene se lo stato del client non viene aggiornato di recente o se si verificano problemi di coerenza perché "qualcos'altro" sta modificando i dati sul server dietro il client indietro?

Infine, si dice che si

.. non si sa come dovrei sincronizzarlo.

Quali sono esattamente i tuoi problemi? Perché non basta aggiornare lo stato dell'app (swap! app-state update-in ...) dopo aver recuperato i dati dal server, come descritto nello reagent-tutorial?

+0

Ciao grazie per la risposta. Hai ragione: questo è un problema che può sorgere ovunque sia necessario sincronizzare lo stato in più punti. Ma sono specificamente alla ricerca di un modo per affrontarlo in reagente/clojurescript come è quello che sto costruendo in (pigro di me?) –

+0

Mentre potrei restituire tutto lo stato di nuovo nella richiesta POST, penso che questo tipo di violi REST un po. Il tutorial sui reagenti non copre l'interazione lato server, ma suppongo che stiano sostenendo POST-then-GET, questo è certamente il modo in cui ho visto funzionare in altri posti (ad es. Https://github.com/clojurecup2014/ amichevole /). Sembra vergognoso che tu perdi tutta la reattività di React in questo modo aspettando 2 round trip dal server. –

+2

Vedere una discussione qui su SO: https://stackoverflow.com/questions/19199872/best-practice-for-restful-post-response – schaueho

1

Questa è una grande domanda circa la sincronizzazione client-server che la maggior parte applicazioni web lottano con.

C'è una libreria Tonsky per il vero problema:

https://github.com/tonsky/datascript

leggere il suo post sul blog e l'esempio datascript-chat per capire il disegno. Questo richiederà molto da imparare, ma temo che sia l'unico modo che non è "non mi sembra giusto".

+0

Grazie per la risposta, ma da un breve sguardo a questo, sembra che questo si concentri principalmente sulla creazione di un database sul lato client. Vedo che c'è una funzione di callback per permettermi di costruire qualcosa per scrivere transazioni sul server, ma non penso che il mio sia il caso d'uso principale di datascript: aggiunge molta complessità extra ma non affronta il mio problema . O mi sono perso qualcosa? –

+1

Rob, DataScript non risolve il problema esatto senza problemi (sincronizzazione client-server), ma è una buona base per un'architettura sana, semplice e affidabile. DS ha il formato della transazione e semplifica la serializzazione dei delta di stato. Tutto ciò che devi aggiungere è il server push per i delta provenienti dal server e il POST per i delta provenienti dal client. Ecco un esempio di architettura di sincronizzazione client-server costruita con DataScript http://tonsky.me/blog/datascript-chat/ E qui http://tonsky.me/blog/acha-acha/ abbiamo utilizzato websocket per scambio di delta tra client e server. –

1

Come altri hanno notato, questa è una sfida di progettazione comune per qualsiasi applicazione client/server in cui potrebbe essere più di un singolo cliente. Penso che la chiave stia nel guardare da vicino quale stato è necessario mantenere nel client. Domande come "Il tuo cliente ha effettivamente bisogno di informazioni aggiornate sullo stato del server o del database remoto o è sufficiente disporre di informazioni aggiornate relative alle azioni eseguite dal client? Ad esempio, è necessario sapere cosa c'è in una tabella di database remota dopo un aggiornamento o è sufficiente sapere se l'aggiornamento ha avuto esito positivo o no?

La o Ciò che ho visto, che può portare gli sviluppatori giù per la strada sbagliata, è troppo importante per l'efficienza. Per ottenere efficienza, il design a volte tenta di incorporare troppo stato nel client locale, ritenendo che questo ridurrà il numero di chiamate al server remoto e renderà l'applicazione più reattiva. Tuttavia, spesso si può finire con un'implementazione eccessivamente complessa, difficile da ottenere con un sovraccarico di gestione dello stato locale, che spesso include molte informazioni che sono utilizzate/rilevanti solo in parti limitate o usate di frequente dell'interfaccia client. La prossima cosa che sai, la tua app sta perdendo efficienza in quanto funziona per mantenere la sincronizzazione dello stato che non è necessaria.

La sfida qui è dovuta alla nostra tendenza a pensare ai problemi in modo serializzato. Questo è naturale. Tuttavia, il problema qui non si adatta perfettamente a questo modo di pensare. Lo stato remoto del sistema sta cambiando a un ritmo imprevedibile. Anche se si adotta un'architettura che spinge i cambiamenti verso il cliente, si incontreranno problemi legati all'elaborazione della frequenza con cui tali cambiamenti dovrebbero essere eliminati e quindi come riflettere tali cambiamenti nell'interfaccia in modo tale che l'utente possa ottenere una coerenza e immagine significativa.

Il mio approccio, che è solo uno dei tanti e potrebbe non essere il più ideale, è quello di modellare l'app web sulla stessa falsariga di molti client di database (e in qualche misura anche di STM di Clojure). Lo stato nel client è un'istantanea dello stato remoto in un determinato momento. Potrebbe non essere accurato o aggiornato, ma dovrebbe essere coerente. Quando il cliente invia una modifica, può avere o meno successo, a seconda di cosa è cambiato nel server da quando ho iniziato a inserire la mia modifica nel client. Se ha successo, ha successo totalmente e se fallisce, fallisce totalmente.

Come sottolineato da altri, questo non ha alcuna relazione diretta con il Reagente. Questo è un problema di design borader. Tuttavia, potrebbe avere un impatto indiretto. Ad esempio, quando si aggiorna l'atomo di reagente, il reagente contenuto verrà visualizzato.L'atomo è consapevole quando viene aggiornato, ma non è a conoscenza quando l'aggiornamento è solo un aggiornamento delle informazioni esistenti senza modifiche, quindi in realtà si desidera aggiornare l'atomo solo quando è necessario aggiornarlo perché qualcosa è cambiato. Tuttavia, a meno che ciò avvenga davvero molto frequentemente e la tua componente è davvero molto complicata, probabilmente non vedrai alcun impatto reale anche se fai frequenti aggiornamenti del tipo di aggiornamento.

Mi concentrerei sul mantenere lo stato al minimo e sullo sviluppo di un progetto davvero semplice, quindi caricare il test e risolvere se ci sono problemi di prestazioni e gestirli nel momento in cui si presentano.