javascript node.js bluebird

javascript - Promise.all consume toda mi RAM



node.js bluebird (1)

Utilizará una cantidad menor de memoria si nunca tiene 58k promesas, sus operaciones asíncronas asociadas y sus datos de resultados activos a la vez.

En cambio, desea ejecutar operaciones X de una vez y luego, cuando finalice, comience la siguiente con nunca más de X en vuelo al mismo tiempo y nunca más de X promesas en uso a la vez.

Puede experimentar con un valor apropiado de X. Un valor de 1 son operaciones secuenciales, pero a menudo puede mejorar el tiempo total de operación de extremo a extremo utilizando un valor mayor de X. Si todas las solicitudes llegan al mismo host, entonces X es probablemente no más de 5-10 (ya que un host determinado no puede hacer muchas cosas a la vez y pedirle que haga más de lo que puede hacer a la vez solo lo ralentiza).

Si cada solicitud es a un host diferente, entonces puede hacer que X sea más alto. La experimentación le daría un valor óptimo tanto para el uso máximo de memoria como para el rendimiento general y, en cierta medida, depende de sus circunstancias específicas.

Promise.map() Bluebird tiene una opción de concurrencia que lo hará por usted, pero también hay numerosas formas de codificar solo X en vuelo al mismo tiempo.

Estos son algunos otros ejemplos de codificación para administrar cuántos están en vuelo a la vez:

Realice varias solicitudes a una API que solo puede manejar 20 solicitudes por minuto

¿Cómo ejecutar promesas en serie?

incapaz de completar promesas por falta de memoria

Dispara 1,000,000 de solicitudes 100 a la vez

¿Cómo hacer que pueda ejecutar, digamos, 10 promesas a la vez en javascript para evitar los límites de velocidad en las llamadas de API?

Si no necesita los datos resueltos, puede permitir que se GCed antes reemplazándolos así:

const p = backgroundScheduler.getClanProfile(clanTags[i], true).then(data => { return 0; // make resolved value just be a simple number // so other data is now eligible for GC }); promiseArray.push(p)

Y, aquí hay una implementación simple que itera una matriz con no más de X solicitudes en vuelo al mismo tiempo:

// takes an array of items and a function that returns a promise // runs no more than maxConcurrent requests at once function mapConcurrent(items, maxConcurrent, fn) { let index = 0; let inFlightCntr = 0; let doneCntr = 0; let results = new Array(items.length); let stop = false; return new Promise(function(resolve, reject) { function runNext() { let i = index; ++inFlightCntr; fn(items[index], index++).then(function(val) { ++doneCntr; --inFlightCntr; results[i] = val; run(); }, function(err) { // set flag so we don''t launch any more requests stop = true; reject(err); }); } function run() { // launch as many as we''re allowed to while (!stop && inflightCntr < maxConcurrent && index < items.length) { runNext(); } // if all are done, then resolve parent promise with results if (doneCntr === items.length) { resolve(results); } } run(); }); }

Tengo un limitador de velocidad para una API que estoy usando que permite 20 solicitudes por segundo. Todas las solicitudes se basan en promesas y la promesa se resolverá con los datos de la API una vez que haya una respuesta.

El problema:

Configuré un array de promesas que contiene 58k promesas, todas esperando una respuesta. Lentamente, la memoria aumenta hasta que me estoy quedando sin memoria. En mi situación específica, no necesito pasar los datos resueltos a mi then() y los datos están consumiendo toda mi RAM.

El código:

}).then(() => { // 2. Crawl for all clanprofiles from these leaderboards const promiseArray = [] for (let i = 0; i < clanTags.length; i++) { // Resolved data from getClanProfile() is eating up all my RAM const p = backgroundScheduler.getClanProfile(clanTags[i], true) promiseArray.push(p) } return Promise.all(promiseArray) }).then(() => {

Entonces, ¿hay alguna manera de esperar hasta que se resuelva la promesa Array sin necesitar los datos resueltos?