• בלוג
  • עמוד 250
  • הפקודות async ו await ישנו את כל מה שידעתם על JavaScript

הפקודות async ו await ישנו את כל מה שידעתם על JavaScript

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

אחד הרעיונות הראשונים שלמדנו בתכנות JavaScript היה שפקודות מתבצעות פקודה אחר פקודה לפי הסדר. בהיעדר Threads לא ייתכן שבאמצע ביצוע פונקציה נעבור לבצע קוד מפונקציה אחרת. לפחות עד שהגיעו async ו await לדפדפנים שלכם.

חדש באתר: קורס JavaScript ES6 בו תלמדו הכל על Promises, תכנות אסינכרוני ועוד עשרות פיצ׳רים חדשים של גרסאות ES6, ES7 ו ES8

1. קפה שחור ומר

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

function getData() {
    const xhr = new XMLHttpRequest();
    xhr.open('GET', 'https://swapi.co/api/people/1/?format=json');
    xhr.addEventListener('load', function() {
        const responseText = xhr.responseText;
        // show response text
    });
    xhr.send();
}

בעיה אחת עם הסגנון היא שככל שיהיו יותר קריאות אסינכרוניות נראה גלישה ימינה של כל בלוק. בעיה יותר חמורה היא שתחום הגדרת המשתנים שונה בין הפונקציות (רק חשבו מה קורה ל this בין כל ה callbacks האלה). העסק ממשיך להסתבך אם מישהו ירצה מבחוץ להפעיל את getData ולחכות שתסיים. במצב כזה נצטרך לשנות את חתימת הפונקציה ולאפשר קבלת callbacks נוספים.

2. סוכר תחבירי מתוק (מדי)

הפקודות async ו await נועדו לפתור את כל הבעיות הללו. הפקודה async מסמנת פונקציה כאסינכרונית, כלומר פונקציה שהיא למעשה מספר פונקציות. בתוך גוף הפונקציה הפקודה await ״חותכת״ את הפונקציה וכל הקוד שאחריה יופעל במעין callback.

נתבונן בקוד הבא:

async function showNext() {
  const val = await getAnotherOne();
  sname.textContent = val.name;
  shair.textContent = val.hair_color;
}

הפונקציה היא אסינכרונית ולכן נחתכת בכל מקום שיופיע await. כבר בשורה הראשונה פקודת await מחלקת את הפונקציה ל-2: תחילה מפעילים את getAnotherOne, וכשזו מסיימת יופעל מעין Callback ובתוכו שתי השורות הבאות. כל המנגנון מבוסס על Promises ועובד בגלל שהפונקציה getAnotherOne מחזירה Promise.

ואיך נראה קוד תקשורת? זכרו ש fetch מחזיר Promise ולכן אפשר לשלב אותו עם await בגוף הפונקציה:

async function getAnotherOne() {
  pstatus.textContent = 'Fetching data for: ' + currentPerson;
  const res = await fetch(`https://swapi.co/api/people/${currentPerson}/?format=json`);
  const data = await res.json();
  currentPerson += 1;
  pstatus.textContent = 'done';
  return data;
}

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

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

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