Alles was Sie über Promise.all wissen müssen

Versprechen in JavaScript sind eine der leistungsstarken APIs, mit denen wir Async-Vorgänge ausführen können.

Promise.all bringt Async-Vorgänge auf die nächste neue Ebene, da es Ihnen hilft, eine Gruppe von Versprechungen zusammenzufassen.

Mit anderen Worten, ich kann sagen, dass es Ihnen hilft, gleichzeitige Operationen durchzuführen (manchmal kostenlos).

Voraussetzungen:

Sie müssen wissen, was ein Versprechen in JavaScript ist.

Was ist Promise.all?

Promise.all ist eigentlich ein Versprechen, das eine Reihe von Versprechen als Eingabe verwendet (eine iterierbare). Dann wird es gelöst, wenn alle Versprechen gelöst werden oder eines von ihnen abgelehnt wird.

Angenommen, Sie haben zehn Versprechen (asynchroner Vorgang zum Ausführen eines Netzwerkaufrufs oder einer Datenbankverbindung). Sie müssen wissen, wann alle Versprechen gelöst sind, oder Sie müssen warten, bis alle Versprechen gelöst sind. Sie geben also alle zehn Versprechen an Promise.all weiter. Dann wird Promise.all selbst als Versprechen aufgelöst, sobald alle zehn Versprechen gelöst sind oder eines der zehn Versprechen mit einem Fehler abgelehnt wurde.

Lassen Sie es uns im Code sehen:

Promise.all([Promise1, Promise2, Promise3]) .then(result) => { console.log(result) }) .catch(error => console.log(`Error in promises ${error}`))

Wie Sie sehen können, übergeben wir ein Array an Promise.all. Und wenn alle drei Versprechen gelöst sind, wird Promise.all aufgelöst und die Ausgabe wird getröstet.

Sehen wir uns ein Beispiel an:

// A simple promise that resolves after a given time const timeOut = (t) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(`Completed in ${t}`) }, t) }) } // Resolving a normal promise. timeOut(1000) .then(result => console.log(result)) // Completed in 1000 // Promise.all Promise.all([timeOut(1000), timeOut(2000)]) .then(result => console.log(result)) // ["Completed in 1000", "Completed in 2000"]

Im obigen Beispiel wird Promise.all nach 2000 ms aufgelöst und die Ausgabe wird als Array konsolidiert.

Eine interessante Sache bei Promise.all ist, dass die Reihenfolge der Versprechen eingehalten wird. Das erste Versprechen im Array wird in das erste Element des Ausgabearrays aufgelöst, das zweite Versprechen wird ein zweites Element im Ausgabearray sein und so weiter.

Sehen wir uns ein anderes Beispiel an:

// A simple promise that resolves after a given time const timeOut = (t) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(`Completed in ${t}`) }, t) }) } const durations = [1000, 2000, 3000] const promises = [] durations.map((duration) => { // In the below line, two things happen. // 1. We are calling the async function (timeout()). So at this point the async function has started and enters the 'pending' state. // 2. We are pushing the pending promise to an array. promises.push(timeOut(duration)) }) console.log(promises) // [ Promise { "pending" }, Promise { "pending" }, Promise { "pending" } ] // We are passing an array of pending promises to Promise.all // Promise.all will wait till all the promises get resolves and then the same gets resolved. Promise.all(promises) .then(response => console.log(response)) // ["Completed in 1000", "Completed in 2000", "Completed in 3000"] 

Aus dem obigen Beispiel geht hervor, dass Promise.all wartet, bis alle Versprechen gelöst sind.

Mal sehen, was passiert, wenn eines der Versprechen abgelehnt wird.

// A simple promise that resolves after a given time const timeOut = (t) => { return new Promise((resolve, reject) => { setTimeout(() => { if (t === 2000) { reject(`Rejected in ${t}`) } else { resolve(`Completed in ${t}`) } }, t) }) } const durations = [1000, 2000, 3000] const promises = [] durations.map((duration) => { promises.push(timeOut(duration)) }) // We are passing an array of pending promises to Promise.all Promise.all(promises) .then(response => console.log(response)) // Promise.all cannot be resolved, as one of the promises passed got rejected. .catch(error => console.log(`Error in executing ${error}`)) // Promise.all throws an error. 

Wie Sie sehen können, scheitern alle anderen Versprechen, wenn eines der Versprechen fehlschlägt. Dann wird Promise.all abgelehnt.

Für einige Anwendungsfälle benötigen Sie das nicht. Sie müssen alle Versprechen ausführen, auch wenn einige fehlgeschlagen sind, oder Sie können die fehlgeschlagenen Versprechen später bearbeiten.

Mal sehen, wie man damit umgeht.

const durations = [1000, 2000, 3000] promises = durations.map((duration) => { return timeOut(duration).catch(e => e) // Handling the error for each promise. }) Promise.all(promises) .then(response => console.log(response)) // ["Completed in 1000", "Rejected in 2000", "Completed in 3000"] .catch(error => console.log(`Error in executing ${error}`)) view raw

Anwendungsfälle von Promise.all

Angenommen, Sie müssen eine große Anzahl von Async-Vorgängen ausführen, z. B. das Versenden von Massenmarketing-E-Mails an Tausende von Benutzern.

Einfacher Pseudocode wäre:

for (let i=0;i<50000; i += 1) { sendMailForUser(user[i]) // Async operation to send a email }

Das obige Beispiel ist einfach. Aber es ist nicht sehr performant. Der Stapel wird zu schwer und zu einem bestimmten Zeitpunkt verfügt JavaScript über eine große Anzahl offener HTTP-Verbindungen, die den Server möglicherweise beschädigen.

Ein einfacher performanter Ansatz wäre, dies in Chargen zu tun. Nehmen Sie die ersten 500 Benutzer, lösen Sie die E-Mail aus und warten Sie, bis alle HTTP-Verbindungen geschlossen sind. Und dann nehmen Sie die nächste Charge, um sie zu verarbeiten und so weiter.

Sehen wir uns ein Beispiel an:

// Async function to send mail to a list of users. const sendMailForUsers = async (users) => { const usersLength = users.length for (let i = 0; i  { // The batch size is 100. We are processing in a set of 100 users. return triggerMailForUser(user) // Async function to send the mail. .catch(e => console.log(`Error in sending email for ${user} - ${e}`)) // Catch the error if something goes wrong. So that it won't block the loop. }) // requests will have 100 or less pending promises. // Promise.all will wait till all the promises got resolves and then take the next 100. await Promise.all(requests) .catch(e => console.log(`Error in sending email for the batch ${i} - ${e}`)) // Catch the error. } } sendMailForUsers(userLists)

Betrachten wir ein anderes Szenario: Sie müssen eine API erstellen, die Informationen von mehreren APIs von Drittanbietern abruft und alle Antworten von den APIs aggregiert.

Promise.all ist der perfekte Weg, dies zu tun. Mal sehen wie.

// Function to fetch Github info of a user. const fetchGithubInfo = async (url) => { console.log(`Fetching ${url}`) const githubInfo = await axios(url) // API call to get user info from Github. return { name: githubInfo.data.name, bio: githubInfo.data.bio, repos: githubInfo.data.public_repos } } // Iterates all users and returns their Github info. const fetchUserInfo = async (names) => { const requests = names.map((name) => { const url = `//api.github.com/users/${name}` return fetchGithubInfo(url) // Async function that fetches the user info. .then((a) => { return a // Returns the user info. }) }) return Promise.all(requests) // Waiting for all the requests to get resolved. } fetchUserInfo(['sindresorhus', 'yyx990803', 'gaearon']) .then(a => console.log(JSON.stringify(a))) /* Output: [{ "name": "Sindre Sorhus", "bio": "Full-Time Open-Sourcerer ·· Maker ·· Into Swift and Node.js ", "repos": 996 }, { "name": "Evan You", "bio": "Creator of @vuejs, previously @meteor & @google", "repos": 151 }, { "name": "Dan Abramov", "bio": "Working on @reactjs. Co-author of Redux and Create React App. Building tools for humans.", "repos": 232 }] */ 

Zusammenfassend ist Promise.all der beste Weg, eine Gruppe von Versprechungen zu einem einzigen Versprechen zusammenzufassen. Dies ist eine der Möglichkeiten, um Parallelität in JavaScript zu erreichen.

Hoffe dir hat dieser Artikel gefallen. Wenn Sie dies getan haben, klatschen Sie bitte und teilen Sie es.

Selbst wenn Sie es nicht getan haben, ist das in Ordnung, Sie können es trotzdem tun: P.