Reputation: 862
I am trying to improve my knowledge of Angular2 by migrating an application currently written in Angular1/AngularJS.
One feature in particular has me stumped. I am trying to replicate a feature where a calling function waits to proceed until the function it is calling has completed a loop of promises. In AngularJS, the function I am calling looks basically like this:
this.processStuff = function( inputarray, parentnodeid ) {
var promises = [];
var _self = this;
angular.forEach( inputarray , function( nodeid ) {
switch ( parentnodeid )
{
case ‘AAA’ : var component = _self.doMoreStuff( nodeid, parentnodeid ); break;
case ‘BBB’ : var component = _self.doMoreStuff( nodeid, parentnodeid ); break;
case ‘CCC’ : var component = _self.doMoreStuff( nodeid, parentnodeid ); break;
default : var component = null;
}
promises.push( component );
});
return $q.all(promises);
};
It contains a forEach
loop that calls another function (doMoreStuff
) that also returns a promise, and it stores all those returned promises in an array.
With AngularJS, when I call processStuff
in another function, I could count on the system waiting until processStuff
completed before entering into the code in the then block:
service.processStuff( arraying, parentidarg )
.then(function( data ) {
...
The caller of processStuff
waits for all doMoreStuff
invocations to complete until the caller of processStuff
enters into its then
block.
I am unsure of how to achieve this with Angular2 and Observables. I can see from these posts that to mimic promises, Observables basically just use subscribe()
instead of then()
:
Angular 1.x $q to Angular 2.0 beta
But how do I await all invocations in the forEach
loop to complete before my application can proceed?
Upvotes: 33
Views: 40655
Reputation: 4592
In RxJS v6 and later you can do this more eloquently with zip.
import { zip } from 'rxjs';
const promise1 = yourSvc.get(yourFavoriteAPI.endpoint1);
const promise2 = yourSvc.get(yourFavoriteAPI.endpoint2);
const promises = zip(promise1, promise2);
promises.subscribe(([data1, data2]) => {
console.log(data1);
console.log(data2);
});
While the result is the same, I find zip
preferable to forkJoin
since zip
is more universal and can handle new values from the observables.
Details from the rxjs documentation:
The zip operator will subscribe to all inner observables, waiting for each to emit a value. Once this occurs, all values with the corresponding index will be emitted. This will continue until at least one inner observable completes.
Upvotes: 4
Reputation: 39258
I have been doing this with forkJoin
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/forkJoin';
Observable.forkJoin(
this.http.get('./friends.json').map((res: Response) => res.json()),
this.http.get('./customer.json').map((res: Response) => res.json())
)
.subscribe(res => this.combined = {friends: res[0].friends, customer: res[1]});
Some more info here: http://www.syntaxsuccess.com/viewarticle/angular-2.0-and-http
Upvotes: 73