Tengo algunas dificultades con algunas llamadas rxjs y me vendría bien un poco de ayuda. Mi problema es buscar una lista de identificaciones, hacer una llamada asíncrona para cada identificación y luego pasar la siguiente identificación una vez que finalice esta llamada asíncrona. Desafortunadamente, no logré encontrar una solución adecuada todavía.
Aquí mi código hasta ahora:
import { from, interval, of, Subject, timer } from 'rxjs'; import { concatMap, filter, flatMap, map, take } from 'rxjs/operators'; const callFinised$ = new Subject(); const makeAsyncCall = val => { console.log('start call for ', val); interval(1000) .pipe(take(1)) .subscribe(() => { callFinised$.next(true); console.log('call finished for ', val); }); }; from(['id1', 'id2']) .pipe( concatMap(val => { return of(val).pipe( flatMap(() => { makeAsyncCall(val); return callFinised$; }), filter(callFinised => callFinised === true), take(1), map(() => { return val + '_updated'; }) ); }) ) .subscribe(finalVal => console.log('finalVal', finalVal));
Aquí el stackblitz asociado: stackblitz
La segunda identificación se emite antes de que finalice la primera asíncrona, por lo que estoy un poco perdido.
Saludos
Aquí hay una versión de su código que (creo) hace lo que busca.
const makeAsyncCall = val => defer(() => { console.log('start call for ', val); return timer(1000).pipe( map(_ => true), tap(_ => console.log('call finished for ', val)) ); }); from(['id1', 'id2']).pipe( concatMap(id => makeAsyncCall(id).pipe( filter(callFinished => callFinished === true), map(_ => id + '_updated') )) ).subscribe(finalVal => console.log('finalVal', finalVal));
Defer no logra nada para usted en el código anterior, ya que llama a makeAsyncCall
básicamente al mismo tiempo que se subscribe
al observable devuelto.
Sin embargo, la creación y la suscripción a Observables son cosas diferentes.
En el siguiente código, primero creo todos los Observables y luego los concateno y los llamo uno tras otro. Sin aplazamiento, este código no generaría lo que espera.
const idCalls = ["id1", "id2"].map(id => makeAsyncCall(id).pipe( filter(callFinished => callFinished === true), map(_ => id + '_updated') ) ); concat(...idCalls).subscribe( finalVal => console.log('finalVal', finalVal) );