1

I need to process each element of an array, making a HTTP call for each element and need to track status of the HTTP call for each call and update UI when everything completes. Currently I have the following code

for (var singleData of this.someData) {
        this._Service.call(singleData.someData).subscribe(
            data=> {
                this.successGroups.push(singleData);
                this.checkState();
            },
            error=> {
                this.failureGroups.push(singleData);
                this.checkState();
            }
        )
    }

this._Service is a simple service which makes a Angular2 HTTP call and returns the observable. The objectives are as follows:

  1. Make calls for each item of list
  2. If success mark as success, failures as failure
  3. Update UI once all calls finish(success/failure is immaterial.)

Problem with above code is that since "singleData" gets updated, incorrect values get pushed. For example by the time subscriber is executed for 1st object of list "singleData" points to say 10th item of list and the 10th item gets instead instead of first.

Nandan Phadke
  • 133
  • 1
  • 1
  • 9
  • A hack would be to pass in the singleData object into the service call and append this into response. Don't like this approach tho. – Nandan Phadke May 13 '16 at 00:19
  • This has nothing to do with Observables or Angular or anything else. It's the classic function-inside-for-loop closure issue. Try `for (let`. –  May 16 '16 at 03:37

1 Answers1

2

You're close, but I would suggest a slightly different approach - something along the lines of:

// Observable.from() takes an array-like value and emits for each element
let requests$ = Observable.from(this.someData)
                          .flatMap(singleData => this._Service.call(singleData.someData);

requests$.subscribe(
   data => {
     this.successGroups.push(singleData);
     this.checkState();
   }, 
   error => {
     this.failureGroups.push(singleData);
     this.checkState();
   }
);

In general, my goal in modeling these things is to minimize the number of Observables and (especially) subscriptions I'm creating. In your current approach, you're creating n of each (where n is the length of your someData array), whereas with this approach you're only creating 1 of each.

drew moore
  • 31,565
  • 17
  • 75
  • 112