Digamos que quiero ejecutar muchas promesas (que aún no están declaradas, por lo que su cuerpo aún no se ha ejecutado). No quiero ejecutarlos en secuencia porque sería muy lento, pero no quiero que se ejecuten todos en paralelo porque sobrecargaría el servidor. Cada una de estas promesas se puede resolver o rechazar muy rápido (alrededor de 1 segundo) o, en el peor de los casos, después de unos 40 segundos. Ninguna de las promesas depende del resultado de ninguna otra. ¿Cuál es la mejor manera de manejar este caso? He visto que una alternativa es usar Promise.all() en lotes de 10 promesas. Sin embargo, esto último no parece ser eficiente teniendo en cuenta que puedo tener 9 promesas que se resuelven muy rápido, pero 1 de ellas se resuelve muy lentamente. Lo que me gustaría lo siguiente:
Digamos que tengo 100 promesas. Comienzo a procesar 10 de ellos, tan pronto como se resuelve uno de ellos, se procesa la promesa número 11, tan pronto como se resuelve el otro, se procesa la promesa número 12, y así sucesivamente. Tenga en cuenta que este comportamiento es diferente al uso de Promise.all() en lotes de 10 porque en ese caso, la promesa 11 a 20 se procesaría después de que se hayan resuelto todas las promesas 1 a 10.
¿Cuál es la mejor manera de implementar esto? Estaba imaginando algo así como tener una cola y tener una función asíncrona processPromise que hace aparecer promesas de esa cola (hasta que esté vacía) y las procesa. Luego haría una matriz de promesas donde cada promesa corresponde a una invocación de processPromise y luego Promise.all() sobre esa matriz. Sin embargo, no estoy seguro de si el acceso simultáneo a esa cola (que es compartido por diferentes invocaciones de processPromise ) sería un problema, o si no tengo nada de qué preocuparme considerando que javascript es de un solo subproceso.
He usado el grupo de promesas para esto:
const { results } = await PromisePool.withConcurrency(10) .for(tasks) .process(async task => { const result = await this.longTask(task); return { result }; });Tenga en cuenta que, sorprendentemente, los resultados no siempre se devuelven en el orden en que los proporcionó, por lo que, dependiendo de su caso de uso, es posible que deba realizar un seguimiento del índice original y clasificarlo al finalizar:
const tasks = items.map((item, index) => ({ item, index })); const { results } = await PromisePool.withConcurrency(10) .for(tasks) .process(async task => { const result = await this.longTask(task.item); return { result, index: task.index }; }); const ordered = results .sort((a, b) => a.index - b.index) .map(result => result.result);