תחי ישראל - אין לנו ארץ אחרת

תחי ישראל -אין לנו ארץ אחרת

הבנת Promise ב-JavaScript

מחבר:
בתאריך:

Promise הוא אובייקט של JavaScript שבתוכו אנחנו שמים קוד, שמחזיר אחת משתי תוצאות, הצלחה או כישלון.

 

התחביר של Promise

האובייקט Promise מקבל פונקציה בתור פרמטר, והפונקציה הזו מקבלת שני פרמטרים: resolve ו-reject.

new Promise(function(resolve, reject) {});

ובתחביר מודרני:

new Promise((resolve, reject) => {});

האובייקט Promise מחזיר אחת מ- 2 מתודות:

  • resolve - שתקרא במקרה שהקוד הצליח.
  • reject - שתקרא במידה והקוד נכשל.

בואו נדגים באמצעות הטלת מטבע:

let flipCoin = new Promise((resolve, reject) => {
  // The code     
  let head = (Math.random() < 0.5);
  
  // Resolve in the case of success
  if(head === true){
    resolve("Yeah, it's head!");
  }

  // Otherwise reject
  reject("No luck this time!");
});

הקוד משתמש בפונקציה rand של JavaScript כדי להציב ערך אקראי למשתנה head, ובמקרה שהערך של head הוא true ה-Promise קורא למתודה resolve, אחרת נקראת המתודה reject.

אם תריצו את הקוד ייתכן שתתאכזבו כי לא תקבלו תוצאה, וזה מפני שאנחנו צריכים לקרוא ל-Promise, וגם לקלוט את התגובה באמצעות המתודות then ו-catch. המתודה then קולטת את ה-resolve, והמתודה catch קולטת את ה-reject.

כך זה נראה:

flipCoin
    .then(fromResolve => console.log(fromResolve))
    .catch(fromReject => console.log(fromReject));

בחיי היום-יום אנחנו משתמשים ב- promise עבור קוד א-סינכרוני.

בחיי היום-יום אנחנו משתמשים ב- promise עבור קוד א-סינכרוני. לדוגמה, קריאה ב-ajax ל-API חיצוני או טעינת תמונה ל-DOM. נחקה את זה באמצעות setTimeout שישהה את התגובה.

let flipCoin = new Promise((resolve, reject) => {
  let head = (Math.random() < 0.5);
  window.setTimeout(() => {
    if(head === true){
      resolve("Yeah, it's a head!");
    }
    reject("No luck this time!");
  }, 1000);
});

flipCoin
    .then(fromResolve => console.log(fromResolve))
    .catch(fromReject => console.log(fromReject));

וזו התוצאה:

מדריך promise של js

* האנימציה ממחישה את ההשהיה עד לקבלת התוצאה.

אז מה היה לנו עד עכשיו? תחביר אובייקט ה-Promise עם המתודות reolve ו-reject, והקוד שקולט את התוצאה של ה-promise באמצעות המתודות then ו-catch.

 

שרשור מתודות

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

talkWithTheCustomer((input) => {
    workOnTheProject((result) => {
        deliverOnTime((finalResult) => {
            console.log('Finito!');
        }, failureCallback);
    }, failureCallback);
}, failureCallback);

בגלל שביצוע הפונקציה deliverOnTime תלוי בהשלמת הפונקציה workOnTheProject נמקם את הפונקציה השנייה בתוך הראשונה, וכן הלאה עד שנסיים עם כל הפונקציות שדרושות לנו להשלמת המשימה.

אבל עדיף קוד מודולרי כי הוא קריא יותר וקל יותר לתחזוקה, ואת זה נוכל לעשות באמצעות תחביר ה-Promise:

talkWithTheCustomer(input)
  .then(result      => workOnTheProject(result))
  .then(result      => deliverOnTime(result))
  .then(finalResult => console.log('Finito!'))
  .catch(fromReject => console.log('Error'));

כדי שהקוד יעבוד נתחיל בכתיבת ההבטחות.

הפונקציה talkWithTheCustomer עוטפת את ה-Promise הראשון שיצליח רק במקרה שהערך של input הוא "agree".

let talkWithTheCustomer = (input) => {
  return new Promise((resolve, reject) => {
    window.setTimeout(() => {
      if(input === 'agree') {
        resolve("OK");
      }
      reject("Sorry, non starter");
    }, Math.random()*1000);
  });
}

שימו לב, חובה להחזיר את ה-Promise באמצעות return אחרת זה לא יעבוד.

עוד טריק קטן שהשתמשתי בו הוא שזמן ההשהיה באמצעות setTimeout נקבע באקראי כדי לחקות את הזמן הלא ידוע עד לקבלת תגובה לקוד א-סינכרוני (לדוגמה, כזה שמגיע מ-API שיושב על שרת מרוחק).

ההבטחה workOnTheProject תצליח במידה והערך של everythingWorked הוא true.

let workOnTheProject = (result) => {
  return new Promise((resolve, reject) => {
    window.setTimeout(() => {
      let everythingWorked = true;
      if(everythingWorked) {
        resolve(result + " >> Everything works according to plan");
      }
      reject("Sorry, can't deliver on time");
    }, Math.random()*2000);
  });
}

כדי לראות את התוצאה, צריך לקרוא ל-promise:

let input = "agree";
talkWithTheCustomer(input)
  .then(result      => workOnTheProject(result))
  .then(finalResult => console.log(`${finalResult} >> The project was delivered!`))
  .catch(fromReject => console.log(`Problem: ${fromReject}`)); //

כל עוד ה-promises מתקיימים, הקוד ממשיך ועובר מפונקציה לפונקציה לפי הסדר של השרשור עד לסיום, אבל במקרה שאחת ההבטחות כושלת, הקוד מפסיק, וקופץ למתודה catch שתופסת פיקוד. כדי לראות כיצד זה פועל נסו לשנות את הערך של המשתנה input , ואז תראו שה-catch הוא זה שמגיב עם ההודעה שמספק ה- reject של הפונקציה הראשונה, והפונקציה השנייה בכלל לא רצה.

 

המתודות all ו-race

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

Promise
  .all([a(), b(), c()])
  .then(()=>console.log("All the functions have finished"));

אם אנחנו יכולים להסתפק בזה שרק אחת הפונקציות תסיים לרוץ כדי להריץ את הקוד, אז נשתמש במתודה race של האובייקט Promise.

Promise
  .race([a(), b(), c()])
  .then(()=>console.log("One of the functions has finished"));

race שימושי כאשר פונים למספר API חיצוניים שעושים את אותה העבודה, ומספיק שאחד מהם מספק את המידע כדי שנוכל להריץ את הקוד שלנו.

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

מדריך JavaScript למתקדמים

 

אהבתם? לא אהבתם? דרגו!

0 הצבעות, ממוצע 0 מתוך 5 כוכבים

 

 

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

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

שימו לב! הסקריפטים במדריכים מיועדים למטרות לימוד בלבד. כשאתם עובדים על הפרויקטים שלכם אתם צריכים להשתמש בספריות וסביבות פיתוח מוכחות, מהירות ובטוחות.

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

השימוש שלך באתר מהווה ראייה להסכמתך עם הכללים והתקנות שנוסחו בהסכם תנאי השימוש.

הוסף תגובה חדשה

 

 

ענה על השאלה הפשוטה הבאה כתנאי להוספת תגובה:

מהם שלוש רשויות השלטון בישראל?

 

תמונת המגיב

איתי בתאריך: 31.03.2018

דוגמה מצוינת. תודה רבה!

תמונת המגיב

יוסי בן הרוש בתאריך: 31.03.2018

השתדלתי :-)

תמונת המגיב

יצחק בתאריך: 18.10.2018

מאמר מצוין

תמונת המגיב

יוסי בן הרוש בתאריך: 18.10.2018

בשמחה

תמונת המגיב

דויד בתאריך: 21.12.2018

מסוכם בצורה מדהימה! מפורט וקל להבנה. תודה

תמונת המגיב

חן בתאריך: 09.11.2019

חשוב ומוסבר יפה. תודה!

תמונת המגיב

שחר בתאריך: 14.01.2020

אלוף!

תמונת המגיב

ישי בתאריך: 07.01.2021

תודה רבה!!!

תמונת המגיב

חיים בתאריך: 03.02.2021

הסבר מעולה!
עזרת לי מאוד!

תמונת המגיב

הילה בתאריך: 07.02.2021

מדהים,
הסבר מעולה!
תודה!

תמונת המגיב

אלון בתאריך: 26.04.2021

דוגמאות מעולות תודה

תמונת המגיב

יעל בתאריך: 26.05.2021

מסביר מעולה!
רציתי לשאול אם גם בpromise All משתמשים כאשר הפונקציות תלויות אחת בשניה?
תודה!

תמונת המגיב

יוסי בן הרוש בתאריך: 27.05.2021

אם אחד תלוי בשני אז משתמשים בשרשור של then

תמונת המגיב

רינת בתאריך: 11.04.2022

מסביר מצוין כמו תמיד!

תמונת המגיב

שיראל בתאריך: 15.11.2022

אתה מלמד בצורה מדהימה!! כיף להיתקל פעם אחר פעם בהסברים המצוינים שלך באינטרנט ולקבל מענה לכל השאלות!