1. מה זה async
ו-await
?
async
ו-await
הם תכונות חדשות יחסית ב-JavaScript (שהוצגו ב-ES2017), שמאפשרות עבודה עם קוד אסינכרוני בצורה נוחה, קריאה ומסודרת יותר מאשר עם Promises בלבד. במקום לשרשר פעולות עם then
ו-catch
, ניתן לכתוב קוד אסינכרוני בסגנון של קוד סינכרוני, וזה מקל מאוד על קריאת הקוד והבנתו.
async
: משמש להגדיר פונקציה כ"אסינכרונית". פונקציה שמוגדרת כ-async
תחזיר תמיד Promise, אפילו אם מחזירים ערך רגיל.await
: משמש בתוך פונקציה אסינכרונית להמתנה ל-Promise שיתקיים. בזמן ההמתנה, הקוד לא ממשיך להתבצע (מבחינת אותה הפונקציה), אך התוכנית כולה ממשיכה לעבוד.
2. התחביר הבסיסי של async
ו-await
התחביר הבסיסי של פונקציה אסינכרונית משתמש במילת המפתח async
לפני ההגדרה של הפונקציה, ומילת המפתח await
משמשת כדי להמתין לפתרון של Promise בתוך הפונקציה.
דוגמה בסיסית:
async function fetchData() {
let data = await fetch('https://jsonplaceholder.typicode.com/posts/1');
let json = await data.json(); // המתנה להמרת התגובה לפורמט JSON
console.log(json);
}
fetchData();
הסבר:
- הפונקציה
fetchData
הוגדרה עםasync
, ולכן ניתן להשתמש ב-await
בתוכה. await
מאפשר להמתין ל-Promise שיתקיים לפני שהקוד ממשיך.- הפונקציה
fetch()
היא אסינכרונית ומחזירה Promise, אז אנחנו משתמשים ב-await
כדי להמתין שהבקשה תסתיים ונוכל לעבד את התוצאה.
3. יצירת פונקציה עם async
כדי להשתמש ב-await
, חייבים להגדיר את הפונקציה עם מילת המפתח async
. זה הופך את הפונקציה לאסינכרונית ומאפשר לה להחזיר Promise אוטומטית.
דוגמה:
async function greet() {
return "Hello!";
}
greet().then(result => console.log(result)); // מציג "Hello!"
הסבר:
- הפונקציה
greet
מוגדרת כ-async
, ולכן היא מחזירה Promise שמתקיים אוטומטית ומחזיר את הערך"Hello!"
. - השימוש ב-
then
מאפשר לנו לקבל את התוצאה ולהדפיס אותה.
4. שימוש ב-await
מילת המפתח await
עוצרת את ביצוע הפונקציה עד ש-Promise מסוים מתקיים ומחזיר תוצאה. היא יכולה לשמש רק בתוך פונקציה שמוגדרת כ-async
.
דוגמה לשימוש ב-await
:
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function displayMessage() {
console.log("Wait for 2 seconds...");
await delay(2000); // המתנה של 2 שניות
console.log("2 seconds passed!");
}
displayMessage();
הסבר:
- הפונקציה
delay
מחזירה Promise שמתממש אחרי מספר מילישניות שניתן לה כפרמטר (במקרה הזה, 2000 מילישניות = 2 שניות). - בתוך הפונקציה האסינכרונית
displayMessage
, אנחנו משתמשים ב-await
כדי להמתין שההמתנה תסתיים לפני שהקוד ממשיך. - הפלט יהיה:
Wait for 2 seconds...
2 seconds passed!
5. טיפול בשגיאות עם try...catch
כאשר משתמשים ב-async
ו-await
, ניתן לטפל בשגיאות בצורה מסודרת בעזרת בלוק try...catch
. זה מאפשר לנהל שגיאות בתוך פונקציות אסינכרוניות באופן נקי יותר מאשר עם catch
של Promises.
דוגמה לשימוש ב-try...catch
:
async function fetchData() {
try {
let response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
if (!response.ok) {
throw new Error('Network response was not ok');
}
let data = await response.json();
console.log(data);
} catch (error) {
console.log("Error:", error.message);
}
}
fetchData();
הסבר:
- עטפנו את הקוד האסינכרוני בבלוק
try
כדי לנסות להפעיל אותו. - אם מתרחשת שגיאה (כמו בעיה ברשת), הקוד בבלוק
catch
יתפוס את השגיאה ויטפל בה. - אם הבקשה לרשת לא מצליחה או מתקבלת תשובה לא תקינה, נזרוק שגיאה עם
throw
שתטופל ב-catch
.
6. פונקציות async
שמחזירות ערכים
פונקציה אסינכרונית מחזירה תמיד Promise. כאשר מחזירים ערך רגיל בתוך הפונקציה, הוא נעטף אוטומטית ב-Promise שמתקיים עם הערך המוחזר.
דוגמה:
async function calculate() {
return 42;
}
calculate().then(result => console.log(result)); // מציג 42
הסבר:
- הפונקציה
calculate
מוגדרת כ-async
, ולכן היא מחזירה Promise. - הערך המוחזר (42) נעטף ב-Promise שמתקיים, ואנחנו מקבלים אותו דרך
then
.
7. המתנה למספר Promises במקביל עם await
אפשר להמתין למספר Promises במקביל בעזרת Promise.all
, ולהשתמש ב-await
כדי להמתין שכולם יסתיימו לפני שהקוד ממשיך.
דוגמה:
async function fetchMultiple() {
let [post, user] = await Promise.all([
fetch('https://jsonplaceholder.typicode.com/posts/1').then(res => res.json()),
fetch('https://jsonplaceholder.typicode.com/users/1').then(res => res.json())
]);
console.log("Post:", post);
console.log("User:", user);
}
fetchMultiple();
הסבר:
- הפונקציה
fetchMultiple
משתמשת ב-Promise.all
כדי להפעיל שתי בקשות רשת במקביל. - עם
await
, אנחנו ממתינים עד ששתיהן יסתיימו לפני שהקוד ממשיך. - הפלט יכלול את התוצאות של שתי הבקשות.
8. דוגמה מלאה: תהליך אסינכרוני עם async
ו-await
נבנה דוגמה שמדמה תהליך של בדיקת קובץ, הורדה שלו ועיבודו באמצעות async
ו-await
.
function checkFile() {
return new Promise((resolve, reject) => {
console.log("Checking file...");
setTimeout(() => resolve("File exists"), 1000);
});
}
function downloadFile() {
return new Promise((resolve, reject) => {
console.log("Downloading file...");
setTimeout(() => resolve("File downloaded"), 2000);
});
}
function processFile() {
return new Promise((resolve, reject) => {
console.log("Processing file...");
setTimeout(() => resolve("File processed"), 1500);
});
}
async function handleFile() {
try {
let fileCheck = await checkFile();
console.log(fileCheck); // "File exists"
let download = await downloadFile();
console.log(download); // "File downloaded"
let process = await processFile();
console.log(process); // "File processed"
} catch (error) {
console.log("Error:", error);
} finally {
console.log("Process completed.");
}
}
handleFile();
הסבר:
- כל אחת מהפונקציות (
checkFile
,downloadFile
,processFile
) מחזירה Promise שמדמה פעולה אסינכרונית. - הפונקציה
handleFile
משתמשת ב-await
כדי להמתין שהפעולות יסתיימו לפני שהקוד ממשיך. - טיפול בשגיאות מתבצע באמצעות
try...catch
, ופעולה סופית מתבצעת ב-finally
.
סיכום
בפרק זה למדנו על:
- איך להשתמש ב-
async
כדי להגדיר פונקציות אסינכרוניות. - איך להשתמש ב-
await
כדי להמתין לתוצאה של Promise לפני שהקוד ממשיך. - איך לטפל בשגיאות בעזרת
try...catch
בתוך פונקציות אסינכרוניות. - עבודה עם מספר Promises במקביל באמצעות
Promise.all
ו-await
. - בניית תהליכים אסינכרוניים קריאים ונוחים לניהול בעזרת
async
ו-await
.
בפרק הבא נעמיק בנושא Object-Oriented JavaScript ונראה איך לעבוד עם מחלקות (Classes) וירושה (Inheritance) ב-JavaScript.