Parallelismo limitato con async / attendi in Typescript / ES7

Ho sperimentato un po ‘con Typescript, ma ora sono un po’ bloccato su come usare async / attendere in modo efficace.

Sto inserendo un gruppo di record in un database e ho bisogno di ottenere l’elenco degli ID restituiti da ciascun inserto. Il seguente esempio semplificato funziona in generale, ma non è abbastanza elegante come mi piacerebbe ed è completamente sequenziale.

async function generatePersons() { const names = generateNames(firstNames, lastNames); let ids = [] for (let name of names) { const id = await db("persons").insert({ first_name: name.firstName, last_name: name.lastName, }).returning('id'); ids.push(id[0]) } return ids } 

Ho provato a usare la map per evitare di creare manualmente la lista degli ids , ma potrei farlo funzionare.

Ciò che vorrei anche avere è un numero limitato di parallelismi. Quindi le mie chiamate asincrone dovrebbero accadere in parallelo fino a un certo limite, ad es. Vorrei solo avere 10 richieste aperte, ma non di più.

Esiste un modo abbastanza elegante per ottenere questo tipo di parallelismo limitato con async / await in Typescript o Javascript ES7? O sto cercando di ottenere questa funzione per fare qualcosa per cui non è stata progettata?

PS: So che ci sono metodi di inserimento di massa per i database, questo esempio è un po ‘artificiale perché potrei usare quelli per aggirare questo problema specifico. Ma mi ha fatto riflettere sul caso generale in cui non ho a disposizione metodi bulk predefiniti, ad esempio con richieste di rete

Promise.all ti permetterà di aspettare che tutte le richieste smettano di finire, senza bloccarne la creazione.

Tuttavia, sembra che tu voglia bloccare a volte. In particolare, sembrava che volessi limitare il numero di richieste in volo in un dato momento. Ecco qualcosa che ho montato (ma non ho completamente testato!)

 async function asyncThrottledMap(maxCount: number, array: T[], f: (x: T) => Promise) { let inFlight = new Set>(); const result: Promise[] = []; // Sequentially add a Promise for each operation. for (let elem of array) { // Wait for any one of the promises to complete if there are too many running. if (inFlight.size >= maxCount) { await Promise.race(inFlight); } // This is the Promise that the user originally passed us back. const origPromise = f(elem); // This is a Promise that adds/removes from the set of in-flight promises. const handledPromise = wrap(origPromise); result.push(handledPromise); } return Promise.all(result); async function wrap(p: Promise) { inFlight.add(p); const result = await p; inFlight.delete(p); return result; } } 

Sopra, inFlight è un insieme di operazioni attualmente in corso.

Il result è una serie di Promise avvolti . Ognuna di quelle promesse avvolte aggiunge o rimuove fondamentalmente le operazioni dall’insieme delle operazioni inFlight . Se ci sono troppe operazioni in volo, allora usa Promise.race per completare una qualsiasi delle operazioni in volo.

Speriamo che questo aiuti.

Controlla la libreria parallela asincrona che offre varie funzioni di supporto che semplificano l’esecuzione di operazioni parallele. Usando questa libreria il tuo codice potrebbe sembrare qualcosa del genere …

 async function generatePersons(): Promise { const names = generateNames(firstNames, lastNames); return await Parallel.map(names, async (name) => await db("persons").insert({ first_name: name.firstName, last_name: name.lastName, }).returning('id')); } 

Se vuoi limitare il numero di istanze a dire quattro alla volta puoi semplicemente fare quanto segue …

 Parallel.concurrency = 4; 

Esiste un modo abbastanza elegante per ottenere questo tipo di parallelismo limitato con async / await in Typescript o Javascript ES7

Dovrai usare Promise.all . vale a dire raccogliere tutte le promesse in un array e await Promise.all([all,the,stuff]) .

Di Più

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all