2014-11-03 16 views
17

In JavaScript il pattern dell'osservatore viene usato abbastanza spesso. C'è una cosa complicata e sono i riferimenti che il soggetto conserva degli osservatori. Hanno bisogno di pulizia. Per le applicazioni regolari utilizzare le seguenti regole di massima:La programmazione reattiva funzionale in JavaScript causa problemi maggiori con i riferimenti listener?

  • Se il soggetto ha una durata di vita più breve rispetto (o uguale a) l'osservatore, posso solo fare subject.on('event', ...)
  • Se il soggetto ha una durata di vita più lunga che l'osservatore, devo usare observer.listenTo(subject, 'event', ...)

Nel secondo caso, il listenTo è consapevole del ciclo di vita dell'osservatore e rimuoverà automaticamente ascoltatori quando è il momento per l'osservatore morire.

Nell'attuale stile SPA (Single Page Application), in cui solo alcune parti dell'applicazione sono attive in qualsiasi momento, questo è qualcosa che diventa molto importante. Se lo combini con le prese per il web, che sono un candidato perfetto per un flusso di eventi e molto probabilmente vissuto da molto tempo, questo diventa ancora più importante.

Con FRP, avendo qualcosa come un flusso di eventi che rappresenta i valori che cambiano nel tempo, sono (senza saperlo) creare molti ascoltatori. Ogni filter, map e flatMap crea un nuovo flusso collegato (probabilmente utilizzando un listener) al precedente.

Nella mia mente sembra abbastanza difficile determinare come e quando ho bisogno di rimuovere quegli ascoltatori. Non riesco a immaginare di essere il primo a pensare a questo problema, ma non ho potuto trovare molto su questo su Internet.

Ho visto alcuni framework in altre lingue utilizzare riferimenti deboli. JavaScript non ha il concetto di riferimenti deboli (WeakMap non è utilizzabile qui). Anche se lo fosse, sembra una cattiva idea perché non è chiaro quando avviene la garbage collection.

  • Come si risolve questo negli attuali framework?
  • Le strutture si legano al ciclo di vita degli oggetti? Se sì: come?
+1

Se pensi che questa domanda debba essere chiusa, per favore aggiungi un commento. Forse aggiungere un suggerimento per rendere la domanda più specifica. O forse un puntatore a un punto in cui questa domanda è più adatta. Se non è chiaro, si prega di fare domande. Voglio davvero usare FRP. – EECOLOR

+0

Mi dispiace dover votare per chiudere. Questa domanda è fin troppo aperta. –

+0

@JK. Hai qualche suggerimento su come migliorare la domanda? – EECOLOR

risposta

11

In RxJ, ogni Observer avrà, per impostazione predefinita, un listener separato sull'origine evento originale. Quindi, se hai

var s = $('#textInput').keyupAsObservable() 
s.subscribe(subscriber1); 
s.map(function() {}).subscribe(subscriber2); 

Avrai due ascoltatori di chiavi. È possibile utilizzare .publish().refCount() per fare in modo che Observable mantenga una singola connessione all'origine.

In Bacon.js, gli Observable mantengono sempre una singola connessione alla loro origine.

In entrambe le librerie la connessione all'origine viene creata pigramente (quando viene aggiunto uno Observer) e rimossa automaticamente quando viene rimosso (l'ultimo) Observer. Pertanto non è necessario gestire manualmente gli ascoltatori.

Tuttavia, nel caso in cui lo subject abbia una durata maggiore rispetto allo Observer, è necessario accertarsi che l'osservatore interrompa l'abbonamento al termine della sua durata o si verifichi una perdita. Nessuna delle due librerie ha un modo "magico" di gestire questo, perché per la libreria, il tuo Observer è solo una funzione.

Personalmente spesso creano un Observable chiamato death o qualsiasi altra cosa per segnalare la fine del ciclo di vita per l'osservatore e poi, invece di sottoscrizione del subject sottoscrivo subject.takeUntil(death).

Per quanto riguarda Elm, la mia comprensione è che hai impostato l'intera rete di eventi contemporaneamente, quindi non c'è possibilità di perdita; Observers non può essere aggiunto in una fase successiva.

+0

La tua comprensione di Elm è corretta, quindi puoi essere più assertivo in quest'ultima affermazione. Il linguaggio consente solo reti di eventi statici (i grafici dei segnali come viene chiamato in Elm), pertanto il codice può essere (ed è) compilato su JavaScript che crea l'intera rete al momento dell'inizializzazione e non deve occuparsi di iscriversi/annullare l'iscrizione. – Apanatshka

+0

La cosa 'morte' è un concetto interessante. È bello sapere che nessuno degli schemi che hai citato ha qualcosa in comune per aiutare con il ciclo di vita. – EECOLOR