Kaikki mitä sinun tarvitsee tietää Promise.allista

JavaScriptin lupaukset ovat yksi tehokkaista sovellusliittymistä, jotka auttavat meitä tekemään Async-operaatioita.

Promise.all vie Async-toiminnot seuraavalle uudelle tasolle, koska se auttaa sinua yhdistämään joukon lupauksia.

Toisin sanoen voin sanoa, että se auttaa sinua tekemään samanaikaisia ​​toimintoja (joskus ilmaiseksi).

Edellytykset:

Sinun on tiedettävä, mikä on JavaScriptin lupaus .

Mikä on Promise.all?

Promise.all on itse asiassa lupaus, joka vie joukon lupauksia syötteenä (iteroituva). Sitten se ratkaistaan, kun kaikki lupaukset ratkaistaan ​​tai joku heistä hylätään.

Oletetaan esimerkiksi, että sinulla on kymmenen lupaa (Async-toiminto verkkopuhelun tai tietokantayhteyden suorittamiseksi). Sinun on tiedettävä, kun kaikki lupaukset ratkaistaan ​​tai joudut odottamaan, kunnes kaikki lupaukset ratkaistaan. Joten välität kaikki kymmenen lupausta Promise.allille. Sitten Promise.all itse lupauksena ratkaistaan, kun kaikki kymmenen lupausta ratkaistaan ​​tai jokin kymmenestä lupauksesta hylätään virheellisesti.

Katsotaanpa se koodina:

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

Kuten näette, välitämme taulukon Promise.all-sivustolle. Ja kun kaikki kolme lupausta ratkaistaan, Promise.all ratkaisee ja tulos lohdutetaan.

Katsotaanpa esimerkki:

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

Yllä olevassa esimerkissä Promise.all ratkaisee 2000 ms: n kuluttua ja lähtö lohistetaan matriisina.

Yksi mielenkiintoinen asia Promise.allissa on, että lupausten järjestys säilyy. Matriisin ensimmäinen lupaus ratkaistaan ​​lähtöryhmän ensimmäiselle elementille, toinen lupaus on toinen elementti lähtöryhmässä ja niin edelleen.

Katsotaanpa toinen esimerkki:

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

Edellä olevasta esimerkistä on selvää, että Promise.all odottaa, kunnes kaikki lupaukset ratkaistaan.

Katsotaanpa, mitä tapahtuu, jos joku lupauksista hylätään.

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

Kuten näette, jos joku lupauksista epäonnistuu, kaikki muut lupaukset epäonnistuvat. Sitten Promise.all hylätään.

Joissakin käyttötapauksissa et tarvitse sitä. Sinun on täytettävä kaikki lupaukset, vaikka jotkut ovat epäonnistuneet, tai ehkä pystyt käsittelemään epäonnistuneet lupaukset myöhemmin.

Katsotaanpa, miten käsitellä sitä.

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

Käytä Promise.all-sovelluksen tapauksia

Oletetaan, että joudut suorittamaan valtavan määrän Async-toimintoja, kuten lähettämään joukkomarkkinointiviestejä tuhansille käyttäjille.

Yksinkertainen pseudokoodi olisi:

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

Yllä oleva esimerkki on yksinkertainen. Mutta se ei ole kovin suorituskykyinen. Pino muuttuu liian raskaaksi, ja yhdellä hetkellä JavaScriptillä on valtava määrä avointa HTTP-yhteyttä, joka voi tappaa palvelimen.

Yksinkertainen suorituskykyinen lähestymistapa olisi tehdä se erissä. Ota ensimmäiset 500 käyttäjää, laukaise posti ja odota, kunnes kaikki HTTP-yhteydet suljetaan. Ota sitten seuraava erä sen käsittelemiseksi ja niin edelleen.

Katsotaanpa esimerkki:

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

Tarkastellaan toista skenaariota: Sinun on luotava sovellusliittymä, joka saa tietoja useilta kolmansien osapuolten sovellusliittymiltä ja yhdistää kaikki vastaukset sovellusliittymistä.

Promise.all on täydellinen tapa tehdä se. Katsotaanpa miten.

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

Lopuksi, Promise.all on paras tapa yhdistää lupaukset yhteen lupaukseen. Tämä on yksi tapa saavuttaa samanaikaisuus JavaScriptissä.

Toivottavasti pidit tästä artikkelista. Jos teit, taputa ja jaa se.

Vaikka et, niin se on hieno, voit tehdä sen joka tapauksessa: P