Async/Await לסנכרון קוד של JavaScript

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

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

נוסף ל- callback ול- promise , התחביר החדש שמאפשר את ההתנהגות הא-סינכרונית נקרא Async/Await , וכדאי להכיר אותו כי במהלך השנים הקרובות יותר ספריות ומפתחים יאמצו אותו.

במדריך זה נזכיר בקצרה כיצד נוהגים להקנות ל-JavaScript התנהגות א-סינכרונית באמצעות callbacks ו- promises, ואז נמשיך להסבר על Async/Await.

מדריך async/await javascript

 

קוד א-סינכרוני באמצעות callback

setTimeout נותן לנו דוגמה קלסית לשימוש ב- callback:

window.setTimeout( ()=> console.log('line 1'),100);
console.log('line 2');

והתוצאה היא ששורה 2 מודפסת לפני שורה 1. אתם מוזמנים לנסות בעצמכם.

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

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

window.setTimeout(()=> console.log('line 1'));
console.log('line 2'); 

למה? callback!
כי הקוד בתוך ה-callback מבוצע אחרי יתר הסקריפט.

זו תכונה שימושית במיוחד כשרוצים להמתין למידע שמגיע משרת מרוחק. לדוגמה, הבאת מידע ב-Ajax באמצעות jQuery:

jQuery.get('https://phpenthusiast.com/dummy-api', (res) => console.log(res));
// The rest of the script

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

שירות ה-api בדוגמה, מחזיר מספר אקראי בין 1 ל-6, כמו בהטלת קובייה.

 

קוד א-סינכרוני באמצעות promise

הדרך החדישה יותר להביא מידע משרת מרוחק היא באמצעות המתודה fetch שמחזירה promise, דהיינו אחת משתי תוצאות אפשריות, הצלחה או כישלון.

fetch('https://phpenthusiast.com/dummy-api/')
  .then((res) => console.log(res)) 
  .catch((error) => console.log(error));

הצלחה, שמשמעותה החזרת המידע המבוקש, מטופלת בבלוק then.

ומקרים של שגיאה, מטופלים באמצעות בלוק catch.

אחד היתרונות של שימוש ב- promises הוא שניתן לחבר אותם אחד לשני לשרשרת של promises שרצים אחד אחרי השני. לדוגמה, כדי לחלץ מידע בפורמט JSON שמגיע באמצעות המתודה fetch() , נוסיף לשרשרת את המתודה json() , שגם היא מחזירה promise().

fetch('https://phpenthusiast.com/dummy-api/') 
  .then((res) => res.json()) 
  .then((data) => console.log(data)) 
  .catch((error) => console.log(error))

מעבר לאלגנטיות של התחביר, השגיאות, ולא משנה באיזה מה- promises הם קורות, מטופלות על ידי אותו בלוק catch.

ל- promise ניתן לשרשר את המתודה all() שמחכה לסיומם של מספר אירועים, לדוגמה אם אנחנו רוצים לקבל מידע ממספר מקורות שונים. ובדוגמה שלנו, אנחנו רוצים לקרוא פעמיים לשירות ה- api כדי לחקות הטלה של שתי קוביות:

const api = 'https://phpenthusiast.com/dummy-api/';
let dice1 = fetch(api);
let dice2 = fetch(api);
Promise.all([dice1,dice2])
// …

כדי למצות את המידע באופן יעיל צריך לשלב את המתודה map():

let dice1 = fetch(api);
let dice2 = fetch(api);
Promise
  .all([dice1,dice2])
  .then(responses => Promise.all(responses.map(res => res.json())))
  .then(results => console.log(`And the result is: ${results[0].random},  ${results[1].random}`))
  .catch(()=>console.log('can\'t throw the dices'));

ולאותה תוצאה ניתן להגיע באמצעות תחביר Async/Await.

 

קוד א-סינכרוני באמצעות Async/Await

התחביר של Async/Await הוא פשוט וקריא יותר מאשר promise , והוא משתמש במילות המפתח async ו- await.

מוסיפים את מילת המפתח async לפני הפונקציה ואת מילת המפתח- await בתוך הפונקציה.

const diceThrower = async () => {
    let dice1 = await dice();
}

הפונקציה שלה קורא ה- await מחזירה promise:

const api = 'https://phpenthusiast.com/dummy-api/';
const dice = () => {
    return fetch(api).then(res => res.json());
}

וה- await ממתין שכל הקריאות לשרת יענו כדי להריץ את יתר הקוד:

const diceThrower = async () => {
    let dice1 = await dice();
    let dice2 = await dice();
    console.log(`The result is: ${dice1.random},  ${dice2.random}`);
}

הקוד קריא הרבה יותר, וכדי לטפל בשגיאות נעטוף אותו ב- try…catch:

const diceThrower = async () => {
    try {
        let dice1 = await dice();
        let dice2 = await dice();
        console.log(`The result is: ${dice1.random},  ${dice2.random}`);
    }  catch(err)  {
        console.log(err);	          
   }	
}

זו הדוגמה המלאה:

const api = 'https://phpenthusiast.com/dummy-api/';
const dice = () => {
    return fetch(api).then(res => res.json());
}
  
const diceThrower = async () => {
    try {
        let dice1 = await dice();
        let dice2 = await dice();	
        console.log(`The result is: ${dice1.random},  ${dice2.random}`);	      
    } catch(err) { 
        console.log(err);	    	
    }
}
diceThrower();

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

 

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

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

 

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

 

= 5 + 3