2016-12-28 12 views
6

Aplikacja My Angular 2 ma 2 metody [GetCategories() i GetCartItems()] w usłudze i obie te metody zwracają Observables.Subskrybuj wiele obiektów Observables w Angular 2

Aby skorzystać z tych dwóch metod jeden po drugim z mojego komponentu, napisałem poniżej kod

ngOnInit() 
{ 
    this.appService.GetCategories().subscribe((data) => { 
     this.appService.categories = data; 


     this.appService.GetCartItems().subscribe({ 
                next: (data) => { this.appService.cart = data}, 
                error: (err) => { this.toaster.error('cart==>' + err)} 

               }) 

    });  
} 

Zasadniczo zawijające GetCartItems od wewnątrz subskrybować od GetCategories() i czuję, że to nie jest właściwe podejście to jest piekielne oddzwanianie.

Każdy pomysł, jak lepiej to wdrożyć (np. "Przyłączyć" do obietnic)?

+1

http://stackoverflow.com/questions/36712659/angular-2-two-backend-service-calls-on-success-of-first-service/36712707#36712707 – echonax

Odpowiedz

10

Wygląda na to, że GetCartItems nie zależy od GetCategories. Następnie można użyć zip:

Observable 
    .zip(
     this.appService.GetCategories() 
     this.appService.GetCartItems() 
    ) 
    .catch(err => this.toaster.error(err)) 
    .subscribe(([categories, cartItems]) => { 
     this.appService.categories = categories; 
     this.appService.cart = cartItems; 
    }); 
+0

myślę 'Observable.combineLatest' to właściwy wybór, a nie "Observable.zip" (jeśli rozumiem problem). Rzeczy mogły się zmienić w ciągu roku, od kiedy to napisałeś. Kiedy używam 'Observable.zip' bez trzeciego argumentu, jak w powyższym przypadku, jedno z wejść jest niezdefiniowane, w zależności od tego, kiedy subskrypcja zostanie uruchomiona. –

7

Jest to najczęściej wykonane z concat(), concatMap() lub ostatecznie concatAll() zależności od usecase i whetrher trzeba zadzwonić zarówno usługi w porządku, czy nie.

function GetCategories() { 
    return Observable.timer(1000).do(() => console.log('GetCategories()')); 
} 

function GetCartItems() { 
    return Observable.timer(1000).do(() => console.log('GetCartItems()')); 
} 

console.log('start...'); 

GetCategories() 
    .concatMap(() => GetCartItems()) 
    .subscribe(() => console.log('done')); 

ten drukuje pocieszyć:

start... 
GetCategories() 
GetCartItems() 
done 

Każdy element jest opóźniony, aby pokazać te nazywane są w kolejności jeden po drugim.

Jeśli nie potrzebujesz zachować tego samego zamówienia, możesz użyć numeru merge() lub mergeMap().

Zobacz demo na żywo: https://jsbin.com/wawajob/1/edit

pamiętać, że korzystanie zip() może mieć niepożądane zachowania. Zobacz https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/zip.md