简体   繁体   中英

How to generate a sequence of Observables from an Observable that emits an array

I have an array of Observable, for simplicity I generate a sample array below

 dataList = of([Array(20).fill(0).map((_r,k) => k)]); // of([1, 2, 3, 4, ..., 20])

The above generates an Observable that emits an array. In the actual code this data is retrieved using an http call

Now what I am trying to achieve is this;

  1. For each of this list generate a new Observable that emits each item after the Other

This I achieve using flatMap operator like below

  flatMap(item => item )
  1. Make an http request. For this I achieve using
  mergeMap(i => this.myService.save(i))
  1. Ensure that each request only starts after the last request

this is where I have a problem

From this demo , I have mocked an http request to return after 1 sec. From the console, all this are returned after 1 sec. But I would like this to be Something like

http/1
http/2 (Delayed until http/1 completes)
http/3 (Delayed until http/2 completes)
http/4 (Delayed until http/3 completes)
...
http/20 (Delayed until http/19 completes)

This is probably what you're after:

of(Array(20).keys()).pipe(
  mergeMap(list => list),
  concatMap(i => this.myService.save(i))
)

The following is another way to do the same thing, though it might make an idiomatic problem a bit more clear to see:

of(Array(20).keys()).pipe(
  mergeMap(list => list.map(
    i => this.myService.save(i)
  )),
  concatAll()
)

concatMap and concatAll store the buffering (backpressure) requests in an array, so it's a bit strange to turn an array into a stream and then immediately turn that stream back into an array.

The following approach skips that step by keeping your array whole and using the static concat operator (which takes an array of observables instead of a stream).

of(Array(20).keys()).pipe(
  map(list => list.map(
    i => this.myService.save(i))
  ),
  switchMap(httpList => concat(...httpList))
)

which can be combined into a single operator like this:

of(Array(20).keys()).pipe(
  switchMap(list => 
    concat(...list.map(
      i => this.myService.save(i)
    ))
  ),
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM