Tengo una variedad de Observables y estoy tratando de hacer 2 cosas:
(1) la siguiente función del bloque de suscripción solo debe llamarse una vez, cuando todo esté hecho, con una matriz de todos los resultados.
(2) los Observables deben dispararse en secuencia, no todos al mismo tiempo.
Aquí está mi código hasta ahora, donde (1) NO funciona y (2) funciona:
const nums = [1, 2, 3]; const obs$ = nums.map((num) => { return rxjs.defer(() => { // this is an async op, mimicking an HTTP call console.log('firing', num); return rxjs.from( new Promise((resolve) => setTimeout(() => resolve(num), 2000)) ); }); }); rxjs.concat(...obs$).pipe( // do something here? ).subscribe( num => { console.log('next', num) }, err => { console.error('error', err.message) }, () => { console.log('complete') } ) <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.6/rxjs.umd.min.js"></script>Salida real:
at 0 secs ... firing 1 at 2 secs ... next 1 at 2 secs ... firing 2 at 4 secs ... next 2 at 4 secs ... firing 3 at 6 secs ... next 3 at 6 secs ... completeSalida deseada:
at 0 secs ... firing 1 at 2 secs ... firing 2 at 4 secs ... firing 3 at 6 secs ... next [1, 2, 3] at 6 secs ... completeTenga en cuenta que los tiempos son importantes aquí.
Ahora sé que forkJoin combina resultados como este. El problema con forkJoin es que firing 1 , firing 2 y firing 3 ocurren al mismo tiempo, pero necesito que se disparen secuencialmente, por eso estoy usando concat .
¿Cómo puedo lograr la salida deseada mientras conservo los tiempos deseados anteriores para firing 1 , firing 2 y firing 3 ?
¡Use toArray dentro de la tubería de concat , ejecutará cada uno y luego llamará al siguiente después de que todo haya terminado!
const nums = [1, 2, 3]; const obs$ = nums.map((num) => { return rxjs.defer(() => { // this is an async op, mimicking an HTTP call console.log('firing', num); return rxjs.from( new Promise((resolve) => setTimeout(() => resolve(num), 500)) ); }); }); let output = []; rxjs.concat(...obs$).pipe( rxjs.toArray(), ).subscribe( num => { console.log('next', num) }, err => { console.error('error', err.message) }, () => { console.log('complete') } ) <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.5.6/rxjs.umd.min.js"></script>