כל מה שאתה צריך לדעת על Promise.all

הבטחות ב- JavaScript הן אחד ממשקי ה- API החזקים שעוזרים לנו לבצע פעולות Async.

Promise.all מעבירה את פעולות Async לשלב החדש הבא מכיוון שהיא עוזרת לך לצבור קבוצת הבטחות.

במילים אחרות, אני יכול לומר שזה עוזר לך לבצע פעולות במקביל (לפעמים בחינם).

תנאים מוקדמים:

עליכם לדעת מהי הבטחה ב- JavaScript.

מה זה Promise.all?

הבטחה.כל היא למעשה הבטחה שלוקחת מערך של הבטחות כקלט (ניתן לחזור). ואז זה ייפתר כאשר כל ההבטחות ייפתרו או שמישהו מהם יידחה.

לדוגמא, נניח שיש לך עשר הבטחות (פעולת Async לביצוע שיחת רשת או חיבור מסד נתונים). אתה צריך לדעת מתי כל ההבטחות ייפתרו או שאתה צריך לחכות עד שכל ההבטחות יפתרו. אז אתה מעביר את כל עשר ההבטחות ל- Promise.all. לאחר מכן, Promise.all כשלעצמו כהבטחה תיפתר ברגע שכל עשר ההבטחות יפתרו או שמישהו מעשר ההבטחות יידחה בשגיאה.

בואו נראה את זה בקוד:

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

כפי שאתה יכול לראות, אנו מעבירים מערך ל- Promise.all. וכשכל שלוש ההבטחות נפתרות, Promise.all נפתרת והתפוקה מנוחמת.

בואו נראה דוגמה:

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

בדוגמה שלעיל, Promise.all נפתרת לאחר 2000 אלפיות השנייה והפלט מנוחם כמערך.

דבר מעניין אחד ב- Promise.all הוא שנשמר סדר ההבטחות. ההבטחה הראשונה במערך תיפתר לרכיב הראשון של מערך הפלט, ההבטחה השנייה תהיה אלמנט שני במערך הפלט וכן הלאה.

בואו נראה דוגמה נוספת:

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

מהדוגמה שלעיל ברור ש- Promise.all ממתין עד שכל ההבטחות יסתיימו.

בואו נראה מה יקרה אם אחת מההבטחות תידחה.

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

כפי שאתה יכול לראות, אם אחת ההבטחות נכשלת, אז כל שאר ההבטחות נכשלות. ואז Promise.all נדחות.

עבור מקרי שימוש מסוימים, אינך זקוק לכך. עליכם לבצע את כל ההבטחות גם אם חלקן נכשלו, או אולי תוכלו להתמודד עם ההבטחות שנכשלו אחר כך.

בואו נראה איך להתמודד עם זה.

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

השתמש במקרים של Promise.all

נניח שעליך לבצע מספר עצום של פעולות Async כמו שליחת מיילים שיווקיים בכמויות גדולות לאלפי משתמשים.

קוד פסאודו פשוט יהיה:

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

הדוגמה לעיל היא פשוטה. אבל זה לא מאוד ביצועי. הערימה תהפוך לכבדה מדי ובנקודת זמן מסוימת, ל- JavaScript יהיה מספר עצום של חיבור HTTP פתוח שעשוי להרוג את השרת.

גישה ביצועית פשוטה תהיה לעשות זאת בקבוצות. קח 500 משתמשים ראשונים, הפעל את הדואר והמתן עד שכל חיבורי HTTP ייסגרו. ואז קח את המנה הבאה כדי לעבד אותה וכן הלאה.

בואו נראה דוגמה:

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

בואו ניקח בחשבון תרחיש נוסף: עליכם לבנות ממשק API שמקבל מידע ממספר ממשקי API של צד שלישי ומאגד את כל התגובות מממשקי ה- API.

Promise.all היא הדרך המושלמת לעשות זאת. בואו נראה איך.

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

לסיום, Promise.all היא הדרך הטובה ביותר לצבור קבוצת הבטחות להבטחה אחת. זו אחת הדרכים להשגת מקביליות ב- JavaScript.

מקווה שאהבתם את המאמר הזה. אם עשית זאת, אנא מחא כפיים ושתף אותו.

גם אם לא עשית זאת, זה בסדר אתה יכול לעשות את זה בכל מקרה: P