Mindössze annyit kell tudni a Promise.all-ról

Az ígéretek a JavaScript-ben az egyik hatékony API, amely segít nekünk az Async műveletek végrehajtásában.

A Promise.all az Async műveleteket egy újabb új szintre emeli, mivel segít az ígéretek egy csoportjának összesítésében.

Más szavakkal azt mondhatom, hogy segít párhuzamos műveletek elvégzésében (néha ingyen).

Előfeltételek:

Tudnia kell, mi az ígéret a JavaScript-ben.

Mi az a Promise.all?

Az Promise.all valójában ígéret, amely ígéretek tömbjét veszi alapul (iterálható). Akkor oldódik meg, amikor minden ígéret megoldódik, vagy bármelyiket elutasítják.

Tegyük fel például, hogy tíz ígérete van (Async művelet hálózati hívás vagy adatbázis-kapcsolat végrehajtására). Tudnia kell, hogy mikor teljesül minden ígéret, vagy meg kell várnia, amíg minden ígéret megoldódik. Tehát mind a tíz ígéretet átadja az Promise.all-nak. Ezután a Promise.all ígéretként megoldódik, ha mind a tíz ígéret megoldódik, vagy a tíz ígéret bármelyikét hibával elutasítják.

Nézzük meg kódban:

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

Mint láthatja, egy tömböt adunk át a Promise.all-nak. És amikor mindhárom ígéret megoldódik, az Promise.all megoldódik, és a kimenet megnyugszik.

Lássunk egy példát:

// 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"]

A fenti példában az Promise.all 2000 ms után megoldódik, és a kimenetet tömbként vigasztaljuk.

A Promise.all minden érdekessége, hogy az ígéretek sorrendje megmarad. A tömb első ígérete megoldódik a kimeneti tömb első elemére, a második ígéret a kimeneti tömb második elemére és így tovább.

Lássunk egy másik példát:

// 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"] 

A fenti példa alapján egyértelmű, hogy az Promise.all megvárja, amíg minden ígéret megoldódik.

Nézzük meg, mi történik, ha az ígéretek bármelyikét elutasítják.

// 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. 

Mint láthatja, ha az egyik ígéret kudarcot vall, akkor az összes többi ígéret kudarcot vall. Ezután a Promise.allt elutasítják.

Bizonyos használati esetekben nincs erre szüksége. Az összes ígéretet akkor is teljesítenie kell, ha némelyik kudarcot vallott, vagy esetleg később kezelheti a nem teljesített ígéreteket.

Lássuk, hogyan kell ezt kezelni.

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

Használja a Promise.all eseteket

Tegyük fel, hogy hatalmas számú Async műveletet kell végrehajtania, például tömeges marketing e-maileket kell küldeni több ezer felhasználónak.

Az egyszerű álkód a következő lenne:

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

A fenti példa egyértelmű. De nem túl teljesítő. A verem túl nehézzé válik, és egy időben a JavaScript hatalmas számú nyílt HTTP-kapcsolattal rendelkezik, ami megöli a szervert.

Egyszerű előadói megközelítés az lenne, ha ezt tételenként végezzük. Fogja az első 500 felhasználót, indítsa el az e-mailt és várja meg, amíg az összes HTTP-kapcsolat meg nem szűnik. Ezután vegye fel a következő adagot annak feldolgozására és így tovább.

Lássunk egy példát:

// 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)
    

Vizsgáljunk meg egy másik forgatókönyvet: Olyan API-t kell készítenie, amely több harmadik fél API-jától kap információkat és összesíti az API-k összes válaszát.

A Promise.all tökéletes módja ennek. Lássuk, hogyan.

// 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 }] */ 

Összegzésként elmondható, hogy a Promise.all minden a legjobb módszer az ígéretek egy csoportjának összesítésére egyetlen ígéretre. Ez az egyik módja annak, hogy elérjük az egyidejűséget a JavaScript-ben.

Remélem tetszett ez a cikk. Ha megtette, kérem, tapsoljon és ossza meg.

Még ha nem is, ez rendben van, akkor is megteheti: P