2015-04-29 27 views
12

Jestem nowy dla RxJS i FRP w ogóle. Miałem pomysł przekształcenia istniejącej obietnicy w mojej aplikacji ExpressJS, aby była możliwa do zaobserwowania w praktyce. Mam świadomość, że to chyba nie jest najlepszy przykład, ale może ktoś może pomóc rzucić trochę światła.Łańcuchowe obietnice z RxJS

Co usiłuję zrobić:

  1. Mam dwie obietnice - prom1 i prom2
  2. chcę prom1 biec przed prom2
  3. Jeśli prom1 wysyła odrzucić (ERR), Chcę anulować prom2, zanim się zacznie.
  4. Chcę, aby komunikat błędu prom1 powrócił do metody onError na obserwatorze.

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

Obietnice nie są "uruchomione", nie można ich "uruchomić". Co masz na myśli? – Bergi

+0

Jaką obietnicę biblioteka używasz, rodzimych obietnic? Jak obsługuje anulowanie? – Bergi

+0

@Bergi - Korzystam z https://github.com/then/promise. Kiedy mówię "run" lub "start", myślę, że to mój sposób na powiedzenie, kiedy obserwowalne jest tworzone i nadaje się do subskrybenta. – Pathsofdesign

Odpowiedz

19

Gdybym zrozumiał, co chce robić - trzeba utworzyć dwa odroczonego obserwable z funkcji, które zwracają obietnic i Concat nich

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'); 
}); 

następnie do normalnego postępowania:

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

I przypadku, gdy nie powiedzie się fisrt obietnica:

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

http://jsfiddle.net/cL37tgva/

+0

Dzięki za to!Odkrywam, że nie muszę używać odroczenia(), ale mogę przekazać obie obietnice w funkcji concat() i uzyskać potrzebne wyniki. Czy brakuje mi czegoś, robiąc to w ten sposób? – Pathsofdesign

+1

W takim przypadku obie obietki zostałyby utworzone (uruchomione) natychmiast (w punkcie, w którym wywołuje się konkatencję, ale nie wtedy, gdy faktycznie subskrybujesz), a druga obietnica nie będzie czekać na odpowiedź przed startem. –

+0

Z odroczeniem(), co jeśli druga obietnica wróci przed pierwszą? Czy to gdzie concat() utrzymuje je w porządku? – Pathsofdesign

5

flatMap okazuje obserwowanej obserwabli w zauważalny. Jest używany w wielu przykładach z Obietnicami, ponieważ często masz funkcję obserwowalną, a w funkcji mapy chcesz stworzyć obietnicę dla każdego "przedmiotu" obserwowalnych emmitów. Ponieważ każde wywołanie fromPromise tworzy nowy Obserwowalny, czyni go "obserwowalnym z obserwowalnych". flatMap redukuje to do "płaskiego" obserwowalnego.

W twoim przykładzie robisz coś innego, zamieniasz pojedynczą obietnicę w obserwowalną i chcesz połączyć ją z inną obserwowalną (również utworzoną z pojedynczej obietnicy). Concat robi to, czego szukasz, łączy ze sobą dwa obserwowalne przedmioty.

Przypadku błędu będzie działać tak, jak można się spodziewać.

-1

Observable.forkJoin działa świetnie tutaj, otrzymując szereg innych obserwowalnych.

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