2015-04-29 13 views
12

Ich bin neu bei RxJS und FRP im Allgemeinen. Ich hatte die Idee, eine bestehende Versprechungskette in meiner ExpressJS-Anwendung so umzuwandeln, dass sie für die Praxis beobachtbar ist. Ich bin mir bewusst, dass dies wahrscheinlich nicht das beste Beispiel ist, aber vielleicht kann jemand helfen, etwas Licht zu geben.Verkettung verspricht mit RxJS

Was ich versuche zu tun:

  1. Ich habe zwei Versprechen - PROM1 und Prom2
  2. I PROM1 vor Prom2
  3. ausgeführt werden soll Wenn PROM1 a (err) sendet ablehnen, Ich möchte prom2 abbrechen, bevor es startet.
  4. Ich möchte, dass die Fehlermeldung prom1 retains für die onError-Methode für den Beobachter verfügbar ist.

var prom1 = new Promise(function(resolve, reject) { 
    if (true) { 
     reject('reason'); 
    } 
    resolve(true); 
}); 

var prom2 = new Promise(function(resolve, reject) { 
    resolve(true); 
}); 

// What do I do here? This is what I've tried so far... 
var source1 = Rx.Observable.fromPromise(prom1); 
var source2 = source1.flatMap(Rx.Observable.fromPromise(prom2)); 

var subscription = source2.subscribe(
    function (result) { console.log('Next: ' + result); }, 

    // I want my error 'reason' to be made available here 
    function (err) { console.log('Error: ' + err); }, 

    function() { console.log('Completed'); }); 
+0

Versprechen werden nicht "ausgeführt", sie können nicht "gestartet" werden. Was meinen Sie? – Bergi

+0

Welche Versprechen Bibliothek verwenden Sie, native Versprechungen? Wie unterstützt es die Stornierung? – Bergi

+0

@Bergi - Ich verwende https://github.com/then/promise. Wenn ich "run" oder "started" sage, denke ich, es ist meine Art zu sagen, wann das Observable erstellt wird und an den Abonnenten sendet. – Pathsofdesign

Antwort

19

Wenn ich verstanden, was Sie zu tun versuchen - Sie zwei latente Observablen von Funktionen erstellen müssen, die Versprechen und verketten sie zurück:

var shouldFail = false; 

function action1() { 
    return new Promise(function (resolve, reject) {  
     console.log('start action1'); 
     if (shouldFail) { 
      reject('reason'); 
     } 
     resolve(true); 
    }); 
} 

function action2() { 
    return new Promise(function (resolve, reject) {  
     console.log('start action2'); 
     resolve(true); 
    }); 
} 

var source1 = Rx.Observable.defer(action1); 
var source2 = Rx.Observable.defer(action2); 

var combination = Rx.Observable.concat(source1, source2); 

var logObserver = Rx.Observer.create(

function (result) { 
    console.log('Next: ' + result); 
}, 

function (err) { 
    console.log('Error: ' + err); 
}, 

function() { 
    console.log('Completed'); 
}); 

dann für Normalfall:

combination.subscribe(logObserver); 
// start action1 
// Next: true 
// start action2 
// Next: true 
// Completed 

Und Fall, in dem fisrt Versprechen nicht:

shouldFail = true; 
combination.subscribe(logObserver); 
// start action1 
// Error: reason 

http://jsfiddle.net/cL37tgva/

+0

Danke dafür!Ich finde, dass ich nicht das defer() Bit gebrauchen muss, aber kann die zwei Versprechenfunktionen in concat() übergeben und die Resultate erhalten, die ich benötige. Fehle ich irgendetwas, indem ich es so mache? – Pathsofdesign

+1

In diesem Fall würden beide Versprechungen sofort erstellt (gestartet) werden (in dem Punkt, wo Sie concat aufrufen, aber nicht, wenn Sie tatsächlich abonnieren) und zweite Versprechen wird nicht warten, zuerst vor dem Start zu lösen. –

+0

Mit dem Defer() s, was passiert, wenn das zweite Versprechen vor dem ersten zurückkehrt? Ist dies der Fall, wenn concat() sie in Ordnung hält? – Pathsofdesign

5

flatMap wendet eine beobachtbare von Observablen in einer beobachtbaren. Es wird in vielen Beispielen mit Promises verwendet, da Sie oft eine Observable haben und in der Map-Funktion ein Versprechen für jedes "Objekt" der beobachtbaren Emmits erstellen möchten. Weil jeder fromPromise-Aufruf ein neues Observable erstellt, das macht es zu einer "beobachtbaren Observablen". flatMap reduziert das auf ein "flaches" Observable.

In deinem Beispiel machst du etwas anderes, du verwandelst ein einzelnes Versprechen in eine beobachtbare und willst es mit einer anderen beobachtbaren verknüpfen (auch aus einem einzigen Versprechen). Concat macht, was Sie suchen, es kettet zwei Observable zusammen.

Der Fehlerfall funktioniert wie erwartet.

-1

Observable.forkJoin funktioniert gut hier erhalten Array von anderen Observables.

Rx.Observable.forkJoin([this.http.get('http://jsonplaceholder.typicode.com/posts'), this.http.get('http://jsonplaceholder.typicode.com/albums')]).subscribe((data) => { 
     console.log(data); 
    });