Estoy tratando de entender cuál es la diferencia entre los métodos mapLimit/queue la biblioteca Async y esta función de solicitud aysnc/await .
Para este ejemplo, digamos que una API tiene un límite de 20 solicitudes por segundo. Estoy usando este script. Mi intención es hacer la solicitud máxima permitida por segundo simultáneamente.
¿Estoy logrando eso con este script?
const data = Array(200).fill(''); const concurrent = 20; let requests = 0; const start = new Date(); (async () => { while (data.length) { // Batched concurret request per second await new Promise((resolve) => setTimeout(resolve, 1000)); const batch = data.splice(0, concurrent).map(API); const results = await Promise.allSettled(batch); // For testing const timeTotal = Math.round((requests / (new Date() - start)) * 1000); console.log(`Requests per second (total): ${timeTotal}/${data.length}`); // Deal with errors for (const { status, reason } of results) { if (status === 'rejected') { console.error(`There was an error ${reason}`); } } } })() async function API() { requests++; await new Promise((resolve) => setTimeout(resolve, 0)); }¿Los métodos antes mencionados están haciendo lo mismo?
Gracias.
El procesamiento por lotes crea "picos" de hasta 20 solicitudes simultáneas, pero espera todas las solicitudes del lote actual antes de iniciar el siguiente lote. Entonces, si 1 de los 20 toma mucho tiempo, solo tendrá ese funcionamiento.
Por el contrario, soluciones como mapLimit inician 20 solicitudes y luego 1 adicional por cada una que finaliza, por lo que siempre hay 20 solicitudes en curso al mismo tiempo.
Me las arreglé para hacer lo mismo que estaba haciendo con lotes pero con solicitudes de grupo.
No pude encontrar nada que hiciera lo mismo, todas las bibliotecas de grupos asíncronos usan Promise.all() Realmente quería usar Promise.allSettled() para aprovechar la oportunidad de volver a ejecutar una solicitud en una condición dada.
Probé p-limit pero al final opté por tiny-async-pool y modifiqué el código fuente para que coincida con mi solicitud por lotes:
export async function asyncPool(poolLimit, array, iteratorFn, exception) { const promises = [] const racers = [] for (const [index, item] of array.entries()) { process.stdout.write(`\rProcessing ${index + 1}/${array.length} ...`) const pro = Promise.resolve().then(() => iteratorFn(item, array)) promises.push(pro) if (poolLimit <= array.length) { const racer = pro.then(() => racers.splice(racers.indexOf(racer), 1)) racers.push(racer) if (racers.length >= poolLimit) { await Promise.race(racers).catch(() => false) } } } const results = await Promise.allSettled(promises) for (const { status, reason } of results) { if (status === 'rejected') { const { name, error } = reason if (name === exception) await asyncPool(poolLimit, [error], iteratorFn) } } }