2016-06-03 18 views
2

Meine Anwendung (Angular 2 mit RxJS 5 in TypeScript geschrieben) erfordert, dass ich in einer vordefinierten Reihenfolge zwei Aufrufe an einen Web-Service anmelde. Inspired by this page Ich entschied mich, den concat-Operator von RxJS-Observablen zu versuchen. Die Wendung ist, dass die onNext Rückruf, der Werte muss leiten sie an verschiedene Handler erhält je nachdem, wo sie herkamenRxJS Observable.concat: Woher weiß man, woher das nächste Ergebnis kommt?

Mein Code kann vereinfacht werden:

suscription1 = Observable.return({name:'John', age:7}); 
subscription2 = Observable.return({name:'Mary', color:'blue'}); 
Observable.concat(subscription1, subscription2).subscribe(
    data=>{ /* need to know which subscripion 
      i'm dealing with to direct to the right handler*/} 
); 

Was die eleganteste Art und Weise ist, um zu bestimmen, wo meine Daten kamen von jeder beobachtbaren Emission? Ich habe an ein paar Möglichkeiten gedacht, aber sie alle scheinen ungeschickt:

  1. Behalten Sie einen Zähler im Bereich, vielleicht als eine Klasseneigenschaft. Überprüfen Sie es und erhöhen Sie es jedes Mal, wenn Sie ein Ergebnis erhalten. Da jede Observable nur einmal ausstrahlt, hat der Zähler seinen Anfangswert, wenn die erste Subskription ausgegeben wird, und er wird initial + 1 haben, wenn die zweite Ausgabe erfolgt. Problem ist, dass dies nicht funktioniert, wenn ich nicht weiß, wie oft jedes Observable ausstrahlt, bevor es vollständig ist.

  2. Untersuchen Sie jedes Ergebnis und identifizieren Sie seine Quelle anhand der Form des Ergebnisses. Zum Beispiel hat in meinem Beispiel nur das Ergebnis der ersten Observablen eine age Eigenschaft. Offensichtlich wird dies unpraktisch, wenn die Ergebnisse die gleiche Form haben.

  3. Entfernen Sie den concat Operator insgesamt; abonnieren Sie subscription2 im onComplete Handler von subscription1. Das würde funktionieren, aber es skaliert nicht gut; wenn ich 4 oder 5 Subskriptionen habe, wird es zur verschachtelten Hölle.

Lösung 3 mit nur 2 Abonnements ...

suscription1 = Observable.return({name:'John', age:7}); 
subscription2 = Observable.return({name:'Mary', age:8}); 
subscription1.subscribe(
    data=> this.handlerOne(data), 
    error=>{}, 
    ()=> { 
     subscription2.subscribe(
      data=>this.handlerTwo(data), 
      error=>{}, 
      ()=>console.log('All subscriptions completed!') 
     ) 
    } 
); 

Also meine Frage: Wenn Observable.concat mit bis zu mehreren Observablen in Folge zu abonnieren, wie kann mein onNext Handler bestimmen, wo aus den Daten gekommen ist? Alternativ, gibt es einen anderen Operator, den ich für diesen Zweck verwenden sollte? Ich kann den Operator forkJoin nicht verwenden, da die Reihenfolge, in der die Abonnements abgeschlossen werden, wichtig ist.

Antwort

2

Sie könnten map die suscriptions wissen, wo es herkommt.

suscription1 = Observable.return({name:'John', age:7}) 
     .map(person => { person.source = 1; return person }; 
subscription2 = Observable.return({name:'Mary', age:8}) 
     .map(person => { person.source = 2; return person }; 

Dann können Sie leicht feststellen, wo es herkommt:

Observable.concat(subscription1, subscription2).subscribe(
    data=> { if (data.source == 1) /* do whatever */ } 
); 
+0

Interessant. Ich dachte "map" könnte nur nach "subscribe" aufgerufen werden, aber offensichtlich nicht. Ich fühlte mich nicht wohl dabei, das 'person'-Ergebnis selbst zu verändern, also änderte ich Ihren Ratschlag, um eine Nebeneigenschaft hinzuzufügen:' .map (e => {return {source: 1, result: e}}) ' – BeetleJuice

+0

In der 2. 'map',' person.source' sollte nicht den gleichen Wert wie in der ersten 'map' haben. Du hast sie beide jetzt auf 1 gesetzt – BeetleJuice

+0

Woops, ja das war dumm, danke für die Korrektur! –