אינטרנט ישראל
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
ראשי » מדריכים » ES20XX » promise.allSettled ב-ES2020

promise.allSettled ב-ES2020

רן בר-זיק דצמבר 22, 2019 7:07 am 4 תגובות

פיצ'ר חדש וחשוב מאוד בכל הנוגע לניהול פרומיסים ושיגור כמה מהם במקביל

»ES2020 Nullish coalescing Operator
»ES2021 replaceAll
כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.

פיצ'ר חדש ב-ES2020 עוזר לנו לנהל את הפרומיסים שלנו טוב יותר בג'אווהסקריפט. ראשית, אני יוצא מנקודת הנחה שכולם יודעים מה זה פרומיסים. מדובר בפיצ'ר סופר משמעותי וחשוב שנכנס לפני כמה שנים לג'אווהסקריפט במסגרת הרפורמה של ES6 ועוזר לנו לנהל קוד באופן אסינכרוני. במאמר הזה הסברתי על פרומיסים ואיך משתמשים בהם (מומלץ גם להשלים את הקריאה עם async-await שנכנס ב-ES2017).

[אני מצטער בנוגע לשימוש בהיבריש אבל כשמדברים על Promises בכל מיני צווי פיתוח בדרך כלל אומרים פרומיסים ולא "הבטחות"]

נשאלת השאלה, איך בדיוק מנהלים כמה פרומיסים במקביל. כלומר נניח ויש לי כמה סרוויסים אסינכרוניים (נניח פונים אל שרת חיצוני כדי לקבל מידע). איך אני מנהל את כולם במקביל? יש לי כמה מתודות. הראשונה היא promise.all. מדובר במתודה שאליה אני יכול להכניס כמה פרומיסים. ברגע שכולם מתמלאים? אני מקבל מערך של כל התוצאות.

הנה דוגמת קוד ואחריה גם דוגמה ב-codepen שאפשר להשתעשע איתה:

const serviceMock1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'Service mock 1 success!');
  });
}

const serviceMock2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 200, 'Service mock 2 success!');
  });
}

const serviceMock3 = () => {
  return new Promise((resolve, reject) => {
    reject('Service mock FAIL!');
  });
}

// Output ["Service mock 1 success!", "Service mock 2 success!"]
Promise.all([serviceMock1(), serviceMock2()]).then((values) => {
  console.log(values); // ["Service mock 1 success!", "Service mock 2 success!"]
});


// Output 'Service mock FAIL!'
Promise.all([serviceMock1(), serviceMock2(), serviceMock3()]).then((values) => {
  console.log('one rejected', values);
}, (error) => {
  console.log('error', error) // 'Service mock FAIL!'
});

See the Pen promise.all demo by Ran Bar-Zik (@barzik-the-vuer) on CodePen.

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

ההתנהגות הזו נקראת short-circuit – בעברית – קצר. בדיוק כמו שהמפסק פחת בלוח החשמל קופץ כשיש בעיית חשמל אחת בכל הבית (למרות ששאר המכשירים בסדר) – כך גם Promise.all – הוא ייכשל למרות שכל הפרומיסים חוץ מאחד (!) הצליחו. מי הצליח? לא נדע.

דרך נוספת לניהול פרומיסים היא עם Promise.race.

המתודה הזו משגרת את כל ההבטחות. הראשונה שחוזרת מנצחת. בין אם מדובר בכשלון או בין אם מדובר בהצלחה. כלומר "מה שיוצא אני מרוצה". אבל רק ההבטחה הראשונה? השאר? מתפוגגות כמו הבטחה של פוליטיקאי אחרי יום בחירות.

הנה הדוגמה:

const serviceMock1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'Service mock 1 success!');
  });
}

const serviceMock2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 200, 'Service mock 2 success!');
  });
}

const serviceMock3 = () => {
  return new Promise((resolve, reject) => {
    reject('Service mock FAIL!');
  });
}

// Output "Service mock 1 success!"
Promise.race([serviceMock1(), serviceMock2()]).then((values) => {
  console.log(values); // "Service mock 1 success!"
});


// Output 'Service mock FAIL!'
Promise.race([serviceMock1(), serviceMock2(), serviceMock3()]).then((values) => {
  console.log('one rejected', values);
}, (error) => {
  console.log('error', error) // 'Service mock FAIL!'
});

See the Pen promise.race demo by Ran Bar-Zik (@barzik-the-vuer) on CodePen.

אפשר לראות שבדוגמה הראשונה אני משגר שני פרומיסים עם Promise.race. אני מקבל הבטחה שמתממשת עם התוצאה הראשונה – הפרומיס שמצליח אחרי 100 מילישניות. מה קורה עם השני? כבר לא מעניין את Promise.race. כשמו כן הוא – מי שמצליח מצליח ראשון וכל השאר? לאבדון.

בדוגמה השניה אני משגר את שלושת הפרומיסים. הכשלון של השלישי הוא זה ש"מנצח" ו-Promise.race מחזירה אותו. כל השאר שהצליחו? מעניינים את הסבתא.

ואחרי ההקדמה המאוד ארוכה הזו, הגיעה העת להסביר על Promise.allSettled. היא מחזירה פשוט מערך עם תוצאות כל הפרומיסים – מי שנכשל ומי שהצליח. הכי פשוט בעולם. פשוט עד כדי גיחוך. בכל איבר בתוצאה יש אובייקט עם סטטוס (הצליח או נכשל) והתוצאה. פשוט, קל ואלגנטי. הנה הדוגמה:

const serviceMock1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 100, 'Service mock 1 success!');
  });
}

const serviceMock2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 200, 'Service mock 2 success!');
  });
}

const serviceMock3 = () => {
  return new Promise((resolve, reject) => {
    reject('Service mock FAIL!');
  });
}

/* 
Output:
[{status: "fulfilled", value: "Service mock 1 success!"},
{status: "fulfilled", value: "Service mock 2 success!"}]
*/
Promise.allSettled([serviceMock1(), serviceMock2()]).then((values) => {
  console.log(values); // "Service mock 1 success!"
});


/*
Output: 
[{status: "fulfilled", value: "Service mock 1 success!"},
{status: "fulfilled", value: "Service mock 2 success!"},
{status: "rejected", reason: "Service mock FAIL!"}]
*/
Promise.allSettled([serviceMock1(), serviceMock2(), serviceMock3()]).then((values) => {
  console.log(values);
}, (error) => {
  console.log('error', error);
});

See the Pen promise.allSettled demo by Ran Bar-Zik (@barzik-the-vuer) on CodePen.

הדוגמה היא פשוטה למדי, promise.allSettled לעולם לא מקצר. הוא פשוט מחזיר את הכל. ההצלחה, הכשלון, הביזיון והנחמה. כפי שנאמר: "תאמר שפחתך יהיה־נא דבר־אדני המלך למנחה כי׀ כמלאך האלהים כן אדני המלך לשמע הטוב והרע וה' אלהיך יהי עמך". אנחנו מקבלים גם את הטוב, גם את הרע. ותודו שזה בדיוק מה שרציתם לראות בבלוג טכנולוגי: פסוקים מהתנ"ך (ספר שמואל ב' לכל הבורים).

בניגוד, אולי, לתנ"ך, promise.allSettled נתמך כבר בכל הדפדפנים חוץ מאקספלורר אהובנו אבל בשביל כל הענתיקות יש את babel להזכירכם.

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.
ES2020

4 תגובות

  1. יונה וילד הגב דצמבר 22, 2019 בשעה 9:35 am

    איך עושים race של רק המוצלחים.
    כלומר אם שילחתי 3 פרומיסים, ואחד חזר מהר אבל עם כישלון אמשיך לחכות עד לראשון מבין ה-2 שנותרו שיחזור עם עלה של זית (הצלחה)?
    (אם ורק אם כולם יכשלו יוחזר כישלון)
    יש דרך לממש את זה?

    • יוסף הגב דצמבר 22, 2019 בשעה 1:10 pm

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

      const onSuccess= value =>{
      console.log('value',value)
      };
      const onErr= value =>{
      console.log('value',value)
      };
      serviceMock1().then(onSuccess,onErr);
      serviceMock2().then(onSuccess,onErr);
      serviceMock3().then(onSuccess,onErr);
      
  2. דוד הגב דצמבר 22, 2019 בשעה 3:11 pm

    נראה לי שברובהמקרים זה יהיה הדרך הכי טובה להשתמש ב-promise

  3. דודו ד. הגב ינואר 2, 2020 בשעה 5:43 pm

    אם allSettled מחזירה פרומסז שהצליחו ושנכשלו, מתי allSettled יכולה להיכשל? במילים אחרות, מתי ה-error callback של allSettled ייקרא?

השארת תגובה

ביטול

ללמוד ג'אווהסקריפט בעברית

ללמוד לתכנת ג'אווהסקריפט בעברית שגייס יותר משלוש מאות אלף שקל ולמעלה מ-2000 תומכים - בואו ללמוד עכשיו איך לתכנת.

רשימת הנושאים
  • מדריכים
    • ריאקט
    • טייפסקריפט
    • ECMAScript 6
    • ES20XX
    • Node.js
    • Express
    • רספברי פיי
    • Babel
    • docker
    • MongoDB
    • Git
    • לימוד MySQL
    • SASS
    • jQuery
    • CSS3
    • HTML 5
    • SVN
    • LESS
  • פיתוח אינטרנט
    • פתרונות ומאמרים על פיתוח אינטרנט
    • jQuery Scripts
    • jQuery למתקדמים
    • יסודות בתכנות
    • נגישות אינטרנט
  • חדשות אינטרנט
  • מידע כללי על אינטרנט
    • רשת האינטרנט
    • בניית אתרי אינטרנט
  • rss logo

    לכל המאמרים

    לכל המאמרים שפורסמו באינטרנט ישראל משנת 2008 ועד עכשיו.
  • rss logo

    RSS Feed

    משתמשים בקורא RSS? אם כן, עקבו אחרי אינטרנט ישראל באמצעות פיד ה-RSS!
    מה זה RSS?
  • Twitter logo

    עקבו אחרי בטוויטר

    בחשבון הטוויטר שלי אני מפרסם עדכונים מהירים על חדשות בתחום התכנות והיזמות, התרעות על מצבי חירום ורכילות בוערת על תחום הווב.
    מה זה טוויטר?
  • facebook like image

    ערוץ הטלגרם של אינטרנט ישראל

    בערוץ הטלגרם של אינטרנט ישראל אני מפרסם את הפוסטים של באתר וכן עדכונים טכנולוגיים נוספים.
    מה זה טלגרם?
  • github logo

    הפרויקטים שלי בגיטהאב

    הפרויקטים שאני כותב ושוחררו לציבור ברישיון קוד פתוח נמצאים ברובם בגיטהאב.
חיפוש

כל הזכויות שמורות לרן בר-זיק ולאינטרנט ישראל | מדיניות הפרטיות של אתר אינטרנט ישראל | אתר אינטרנט ישראל נגיש לפי תקן WCAG 2.0 AA | הצהרת הנגישות של האתר | אבטחת מידע ודיווח על בעיית אבטחת מידע

גלילה לראש העמוד