3

Y a-t-il un moyen de s'assurer que l'ordre de mise à jour des abonnés est assuré? J'ai un observable à chaud et mon premier abonné effectue un travail de synchronisation pour mettre à jour une variable et mon prochain abonné doit ensuite initialiser un service (une seule fois!), Et seulement après que cette variable soit configurée!S'assurer que les abonnés reçoivent une mise à jour

il ressemble à ceci:

import App from './App' 

var appSource = App.init() // gets the hot observable 

// our second subscriber 
appSource.take(1).subscribe(() => { 
    // take 1 to only run this once 
    nextService.init() 
}) 

App.init ressemble à ceci:

... 
init() { 
    var source = this.createObservable() // returns a hot interval observable that fetches a resource every few minutes 

    // first subscriber, updates the `myVar` every few minutes 
    source.subscribe((data) => this.myVar = data) 

    return source 
} 
... 

ceci fonctionne actuellement, mais je ne suis pas sûr si elle suit toujours l'ordre de 100%.

EDIT:

Comme je l'ai entendu, les abonnés seront appelées FIFO. Donc, la commande est quelque peu assurée.

Répondre

2

Je ne sais pas si RxJS garantit explicitement que les observateurs sont appelés dans l'ordre d'abonnement. Mais, comme vous le dites, cela fonctionne habituellement. Toutefois, vous pouvez envisager de modéliser votre flux de travail réel au lieu de vous fier à l'ordre implicite des observateurs.

Il semble que vous ayez besoin de savoir quand votre application est initialisée pour pouvoir prendre d'autres mesures. Au lieu de compter sur la connaissance du fonctionnement interne de App.init, App pourrait exposer une API pour cela:

Un (de façon non-Rx) est de laisser l'appelant fournir un rappel à init:

//... 
init(callback) { 
    var source = this.createObservable() // returns a hot interval observable that fetches a resource every few minutes 

    // first subscriber, updates the `myVar` every few minutes 
    source.subscribe((data) => { 
    this.myVar = data; 
    if (callback) { 
     callback(); 
     callback = undefined; 
    } 
    }) 

    return source 
} 

// elsewhere 
App.init(() => nextService.init()); 

Une autre option au lieu d'un rappel est d'avoir seulement init retourner un Promise que votre résolution (ou un Rx.AsyncSubject que vous signalez) une fois l'initialisation est terminée.

Et encore une autre option, mais nécessite un peu d'un refactor, est de modéliser this.myVar comme les données observables qu'il est. i.e. .:

init() { 
    this.myVar = this.createObservable().replay(1); 
    this.myVar.connect(); 
    // returns an observable that signals when we are initialized 
    return this.myVar.first(); 
} 

// elsewhere, you end up with this pattern... 
const servicesToInit = [ App, service1, service2, service3 ]; 
Observable 
    .of(servicesToInit) 
    .concatMap(s => Rx.Observable.defer(() => s.init())) 
    .toArray() 
    .subscribe(results => { 
     // all initializations complete 
     // results is an array containing the value returned by each service's init observable 
    }); 

Maintenant, tout ce qui veut utiliser myVar aurait toujours besoin de souscrire pour obtenir en someway les valeurs actuelles et/ou futures. Ils ne pourraient jamais demander de façon synchrone la valeur actuelle.

+0

Hey @Brandon, merci pour votre excellente explication! Question sur 'myVar': actuellement,' myVar' représente des données provenant d'une ressource que je dois récupérer toutes les quelques minutes. Pour obtenir ces données j'ai simplement ajouté un 'App.getData()' qui retourne 'this.myVar' quand j'en ai besoin. Je devrais refactoriser mon getMethod à quelque chose comme 'getData => this.myVar.takeLast (1)' pour obtenir les dernières données, correct? –

+0

Encore pire: vous devriez faire 'getData' async:' getData => this.myVar.first() 'et l'appeler comme ceci:' getData(). Subscribe (data => valeur disponible ici); '. Async a tendance à se propager une fois que vous commencez à l'utiliser. C'est pourquoi j'ai dit que c'est un peu un refactor si vous le représentez actuellement comme étant disponible de manière synchrone. – Brandon

+0

Une alternative est de faire ceci: 'this.monVarAsync = this.createObservable(). Do (val => this.myVar = val) .replay (1);'.Cela rendrait la valeur "la plus récente" disponible en tant que variable simple, tout en rendant la valeur changeante asynchrone disponible en tant qu'observable pour quiconque en a besoin. – Brandon