Promise.all consuma tutta la mia RAM

Ho un limitatore di velocità per un’API che sto utilizzando che consente 20 richieste al secondo. Tutte le richieste sono basate su promesse e la promise verrà risolta con i dati API una volta che ci sarà una risposta.

Il problema:

Ho impostato un promemoriaArray che contiene 58k promesse tutti in attesa di una risposta. Così lentamente la memoria sta aumentando fino a quando non esaurisco la memoria. Nella mia situazione specifica non ho bisogno di passare i dati risolti al mio then() e il dato sta divorando tutta la mia RAM.

Il codice:

  }).then(() => { // 2. Crawl for all clanprofiles from these leaderboards const promiseArray = [] for (let i = 0; i  { 

Quindi c’è un modo per attendere fino a quando la promiseArray non viene risolta senza i dati risolti?

Utilizzerai una quantità minore di memoria se non avessi mai promesse da 58k, le loro operazioni asincrone associate e i loro dati di risultato attivi contemporaneamente.

Invece tu vuoi eseguire le operazioni X contemporaneamente e poi quando si finisce, si avvia il prossimo con mai più di X in volo allo stesso tempo e mai più di X promette in uso contemporaneamente.

Puoi sperimentare con un valore appropriato di X. Un valore di 1 è operazioni sequenziali ma puoi spesso migliorare il tempo di funzionamento end-to-end generale utilizzando un valore maggiore di X. Se tutte le richieste stanno colpendo lo stesso host, X probabilmente non più di 5-10 (dato che un determinato host non può davvero fare un sacco di cose contemporaneamente e chiedergli di fare più di quello che può fare subito lo rallenta).

Se ogni richiesta riguarda un host diverso, potresti essere in grado di aumentare X. La sperimentazione potrebbe fornire un valore ottimale sia per l’utilizzo di memoria di picco che per la velocità generale e in qualche modo dipende dalle circostanze specifiche.

Promise.map() ha un’opzione di concorrenza che farà questo per te, ma ci sono anche numerosi modi per codificare solo X in volo allo stesso tempo.

Ecco alcuni esempi di codice di gestione di quanti sono in volo alla volta:

Fai diverse richieste a un’API che può gestire solo 20 richieste al minuto

Come eseguire le promesse in serie?

incapace di completare le promesse a causa di memoria insufficiente

Spara 1.000.000 richieste alla volta

Come fare in modo che io possa eseguire dire 10 promesse alla volta in javascript per prevenire i limiti di velocità sulle chiamate API?


Se non hai bisogno dei dati risolti, puoi permetterne il GCing prima sostituendolo in questo modo:

  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) 

E, ecco una semplice implementazione che itera un array con non più di X richieste in volo allo stesso tempo:

 // 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(); }); }