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?
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With