آموزش جامع Async/Await در جاوااسکریپت
🎯 اهداف یادگیری
- درک مفهوم asynchronous در جاوااسکریپت
- آشنایی با مشکلات callback hell
- یادگیری نحوه کار با Promise
- تسلط بر استفاده از Async/Await برای کدنویسی تمیزتر
📌 برنامهنویسی Asynchronous چیست؟
در جاوااسکریپت، برخی عملیات مانند درخواستهای شبکه یا خواندن فایلها زمانبر هستند و اگر به صورت همزمان (synchronous) اجرا شوند، کل برنامه را مسدود میکنند:
javascript
// مثال کد synchronous (مسدودکننده)const data = fetchDataFromServer(); // این خط تا دریافت داده کامل صبر میکندconsole.log(data);
راهحلهای Asynchronous:
- Callbackها: تابعی که پس از اتمام عملیات فراخوانی میشود
- Promiseها: شیءای که نتیجه آینده یک عملیات را نشان میدهد
- Async/Await: سینتکسی برای کار با Promiseها به صورت خطی
📌 مشکل Callback Hell
استفاده بیش از حد از callbackها منجر به کدی غیرقابل خواندن میشود:
javascript
getUser(userId, function(user) { getPosts(user, function(posts) { getComments(posts[0], function(comments) { console.log(comments); }); });});
معایب Callbackها:
- خوانایی پایین: هرمهای تو در تو (Callback Hell)
- مدیریت خطا سخت: نیاز به بررسی خطا در هر سطح
- جریان کنترل پیچیده: دنبال کردن ترتیب اجرا دشوار است
📌 معرفی Promiseها
Promiseها شیءهایی هستند که نشاندهنده تکمیل یا شکست یک عملیات ناهمزمان هستند:
javascript
const promise = new Promise((resolve, reject) => { if (operationSuccessful) { resolve("عملیات موفق بود!"); } else { reject(new Error("عملیات شکست خورد")); }});promise.then(result => { console.log(result); // "عملیات موفق بود!"}).catch(error => { console.error(error); // "عملیات شکست خورد"});
حالتهای Promise:
- pending: در حال انتظار (حالت اولیه)
- fulfilled: عملیات با موفقیت انجام شد
- rejected: عملیات با شکست مواجه شد
📌 معرفی Async/Await
Async/Await سینتکسی برای کار با Promiseها به صورت خطی و خوانا است:
javascript
async function fetchData() { try { const response = await fetch('https://api.example.com/data'); const data = await response.json(); console.log(data); } catch (error) { console.error('خطا در دریافت داده:', error); }}fetchData();
قوانین Async/Await:
- async: تابعی که حاوی await است باید با async تعریف شود
- await: فقط میتواند داخل توابع async استفاده شود
- try/catch: برای مدیریت خطاها ضروری است
- مقدار بازگشتی: تابع async همیشه یک Promise برمیگرداند
📌 مقایسه روشهای مختلف
Callback | Promise | Async/Await |
---|---|---|
خوانایی پایین | خوانایی متوسط | خوانایی بالا |
مدیریت خطا سخت | مدیریت خطا با catch | مدیریت خطا با try/catch |
زنجیرهکردن سخت | زنجیرهکردن با then | کدنویسی خطی |
📌 تمرین عملی
تابع زیر را که با Promise نوشته شده است، به Async/Await تبدیل کنید:
javascript
function getUserData(userId) { return fetch(`https://api.example.com/users/${userId}`) .then(response => response.json()) .then(data => { console.log(data); return data; }) .catch(error => { console.error('خطا در دریافت داده کاربر:', error); });}
راهنمای تمرین:
- تابع را با async تعریف کنید
- فراخوانیهای then را با await جایگزین کنید
- مدیریت خطا را با try/catch انجام دهید
📌 نکات پیشرفته
- Promise.all: برای اجرای چند Promise به صورت موازی
- Promise.race: برای دریافت اولین Promise تکمیل شده
- Async IIFE: برای اجرای فوری توابع async
- Top-level Await: استفاده از await در ماژولهای ES
javascript
// استفاده از Promise.all برای درخواستهای موازیasync function fetchAllData() { const [user, posts] = await Promise.all([ fetch('/user').then(r => r.json()), fetch('/posts').then(r => r.json()) ]); console.log(user, posts);}
📌 قدم بعدی
در درس بعدی با Fetch API در جاوااسکریپت آشنا خواهیم شد!