Comment exécuter async / attendre en parallèle en Javascript

Enfin, async / await sera pris en charge dans tous les principaux navigateurs, sauf IE. Alors maintenant, nous pouvons commencer à écrire un code plus lisible avec async / await mais il y a une capture. Beaucoup de gens utilisent Async attendent comme ceci:

 const userResponse = await fetchUserAsync(); const postsResponse = await fetchPostsAsync(); 

Bien que ce code soit lisible, il a un problème, il exécute les fonctions en série, il ne commencera pas à chercher des messages jusqu'à ce que la récupération de l'utilisateur soit terminée. Les solutions sont simples, nous devons récupérer les ressources en parallèle.

Donc, ce que je veux faire est (en pseudo-langage):

 fn task() { result-1 = doAsync(); result-2 = doAsync(); result-n = doLongAsync(); // handle results together combinedResult = handleResults(result-1, result-2); lastResult = handleLastResult(result-n); } 

Vous pouvez écrire quelque chose comme ceci:

 const responses = Promise.all([ fetchUserAsync(), fetchPostsAsync(), ]); const userResponse = responses[0]; const postsResponse = responses[1]; 

C'est facile, n'est-ce pas? Mais il ya un hic. Promise.all a un comportement sans échec , ce qui signifie qu'il rejette dès que l'une des promesses est rejetée. Vous voudrez probablement une solution plus robuste où nous sommes chargés de gérer les rejets de toutes les récupérations. Heureusement, il y a une solution, elle peut être obtenue simplement avec async / await sans avoir besoin d'utiliser Promise.all . Un exemple de travail:

 console.clear(); function wait(ms, data) { return new Promise( resolve => setTimeout(resolve.bind(this, data), ms) ); } /** * This will run in series, because * we call a function and immediately wait for it's result, * so this will finish in 1s. */ async function series() { return { result1: await wait(500, 'seriesTask1'), result2: await wait(500, 'seriesTask2'), } } /** * While here we call the functions first, * then wait for the result later, so * this will finish in 500ms. */ async function parallel() { const task1 = wait(500, 'parallelTask1'); const task2 = wait(500, 'parallelTask2'); return { result1: await task1, result2: await task2, } } async function taskRunner(fn, label) { const startTime = performance.now(); console.log(`Task ${label} starting...`); let result = await fn(); console.log(`Task ${label} finished in ${ Number.parseInt(performance.now() - startTime) } miliseconds with,`, result); } void taskRunner(series, 'series'); void taskRunner(parallel, 'parallel'); /* * The result will be: * Task series starting... * Task parallel starting... * Task parallel finished in 500 milliseconds with, { "result1": "parallelTask1", "result2": "parallelTask2" } * Task series finished in 1001 milliseconds with, { "result1": "seriesTask1", "result2": "seriesTask2" } */ 

Si vous n'êtes pas d'accord avec le comportement sécurisé de Promise.all et la syntaxe d'affectation destructrice:

 const [userResponse, postsResponse] = await Promise.all([ fetchUserAsync(), fetchPostsAsync(), ]); 

En fait, je viens de faire la même chose. En utilisant des promesses et ensuite Promise.all pour les synchroniser à la fin, vous pouvez faire de nombreuses demandes simultanées, mais assurez-vous d'avoir tous les résultats avant de terminer.

Voir ici dans le dernier exemple: http://javascriptrambling.blogspot.com/2017/04/to-promised-land-with-asyncawait-and.html