typescript - ¿Cómo esperar a que un observable se complete antes de continuar con el siguiente?
Estoy empezando a aprender sobre los observables, tengo algunas preguntas sobre cómo hacer lo siguiente:
- Tengo un arreglo de objetos.
- Quiero consumir una API para cada elemento en el arreglo.
- Para cada respuesta quiero combinarla en una sola, como un array de objetos de respuesta.
- Estoy consumiendo una API que envía mensajes, así que quiero que cuando se envíe un mensaje, espere antes de continuar con el siguiente elemento.
Estoy usando NestJS (TypeScript)
Ya resolví los primeros 3 ítems.
Mi problema es que estoy consumiendo una API de mensajería, con el código que hice no espera a que un observable termine con la respuesta válida y ya está ejecutando el siguiente, esto afecta a que envíe los mensajes fuera de orden.
return of(individualMessages).pipe(
map(messages => messages.map(body =>
this.sendSingleWhatsappMessage(url, body, config, inputQuery)
.pipe( map((resp) => resp)))),
mergeMap(ApiRes => forkJoin(ApiRes)),
);
por ejemplo, tengo este arreglo
const messages = [ { id: "9r8f", body: "Hello"},{ id: "9r8f", body: "Good morning"}]
para cada elemento del arreglo quiero consumir la API de mensajes
La respuesta de la API es un código de estado con un id
{ statusCode: 200, id="87438fsdfhsd"}
Quiero que devuelva la respuesta de cada consumo combinada en un arreglo
[{ statusCode: 200, id="87438fsdfhsd"}, { statusCode: 200, id="72448fsd66hsd"}]
Hice esto correctamente, mi problema es que la API puede tardar mucho en enviar un mensaje y cuando esto sucede los mensajes se ven desordenados
ejemplo :
- Buenos Días => mensaje 2
- Hola => mensaje 1
Respuesta #1
Tu código original se simplifica a esto:
return of(individualMessages).pipe(
map(messages => messages.map(
({body}) => this.sendSingleWhatsappMessage(url, body, config, inputQuery)
)),
mergeMap(requests => forkJoin(requests)),
);
Comportamiento :
maptransforma tu array deMessagesen un array de solicitudesforkJoincrea un observable único que ejecutará todas las solicitudes al mismo tiempo y devolverá un arreglo con los resultadosmergeMapse suscribe a este "observable forkJoin" interno y emite su resultado (el arreglo de resultados).
Basándome en esto, esperaría que su arreglo de resultados ESTÉ en el orden correcto, pero existe la posibilidad de que no necesariamente se completen en orden secuencial (dado que todos se envían al mismo tiempo, no se garantiza el orden).
Si quieres ejecutar cada solicitud en secuencia, podrías hacer algo como esto:
return from(individualMessages).pipe(
concatMap(({body}) => this.sendSingleWhatsappMessage(url, body, config, inputQuery)),
toArray()
);
Comportamiento :
fromemite cada elemento del array individualmenteconcatMapse suscribirá a cada solicitud "una a la vez" y emitirá su resultadotoArray()recogerá todas las emisiones recibidas y las emitirá como un arreglo una vez que el observable fuente complete
