0

I am building an Angular app. In the constructor of my component, I am initiating a request for several elements from the server, which naturally occur asynchronously. Those requests are returned to me as rxjs/Behavior objects, to which I am subscribed.

What I need to do is continue processing as soon as the last one is back. But I NEED to make sure that they are processed in the order in which they were submitted, not necessarily in the order in which they were returned.

I could create a janky hack to detect when the last one has returned:

let counter = 0;
let output = new Array( input.length );
for ( let i = 0 ; i < input.length ; i++ ) {
  counter++;
  fetch( input[i] ).subscribe( 
    result => {
      output[i] = result;
      counter--;
      if ( counter === 0 ) {
        // what to do at the end
      }
    }
  );
}

And this works. But it's ugly, it is not easy to understand, and not what I would call production-ready code.

What is the Angular way of doing something once an array of subjects have all been fulfilled?

John Arrowwood
  • 2,370
  • 2
  • 21
  • 32
  • You should not be receiving `Subject`s. If you have stewardship of the API in question, use `.asObservable()` to hide the implementation. If you don't then, I suggest that you find a new library. – Aluan Haddad Dec 28 '17 at 21:33

1 Answers1

3

You're looking for forkJoin:

Observable.forkJoin(...input.map(fetch)) 
 .subscribe(responses => {
    // responses contains the emitted values after completion
    // in the same order as input
  });

See the docs for more details and some things to watch out for.

As an extended tip for the future, the rxjs website has a pretty good questionnaire that helps you find the operator you are looking for in various situations.

Ingo Bürk
  • 19,263
  • 6
  • 66
  • 100