Eugeny89
Eugeny89

Reputation: 3731

RxJs: sequential sending of requests is not really sequential

I need to send a set of identical requests sequentially: the next request should be sent only when the previous is complete (i.e. I got the response). I'm having the following code...

Observable.of(ids)
    .pipe(
        concatMap(ids => ids.map(id => this.doRequest(id)))
    )
    .subscribe((res) => { 
        //one more request here 
    })

The next request do not wait for previous to complete. Moreover when I do one more request in subscribe N requests (where N is equal to ids.length) are sent instead of one request.

Can someone explain me what is happening here and how can I fix the problem?

Thank you in advance!

UPD. Looks like it's needed to provide more details on what I'm trying to do. After following @martin answer the code looks like the following

let obj = {ids: [1, 2, 3]};

return Observable.of(obj)
    .filter((tube: ResultTube) => {
        return (
            obj != null &&
            obj.ids &&
            obj.ids.length > 0
        );
    })
    .switchMap(obj => {
        return Observable.from(obj.ids);
    })
    .pipe(
        concatMap(id => this.approveLaboratory(id))
    )
    .map((res) => { 
        debugger; //fired N times after subscribe() !
        return obj 
    })

Upvotes: 0

Views: 59

Answers (1)

martin
martin

Reputation: 96889

If you want concatMap to wait you need to work with single emissions and let it process them one by one. What you have right now pushes ids as an array into concatMap and then creates an array of Observables. Instead you can unpack ids into separate emissions before concatMap:

Observable.from(ids)
  .pipe(
    concatMap(id => this.doRequest(id))
  )
  .subscribe((res) => { 
    //one more request here 
  })

...or like this:

Observable.of(ids)
  .pipe(
    concatAll(), // unpack array of ids
    concatMap(id => this.doRequest(id))
  )
  .subscribe((res) => { 
    //one more request here 
  })

Upvotes: 2

Related Questions