async و await
تابع async کمک میکند مراحل ناهمگام را به همان ترتیبی بنویسیم که خوانده میشوند. await منتظر نتیجهٔ یک Promise میماند، اما فقط ادامهٔ همان تابع را نگه میدارد؛ صفحه یا کل JavaScript متوقف نمیشود.
await دقیقاً چه چیزی را متوقف میکند؟
وقتی اجرای تابع به await میرسد، کنترل موقتاً به مرورگر برمیگردد. در این فاصله رویدادها و کدهای دیگر میتوانند اجرا شوند. بعد از fulfilled شدن Promise، تابع از همان نقطه ادامه پیدا میکند.
خروجی تابع async همیشه Promise است
حتی اگر در تابع async یک رشته را return کنیم، فراخوانی تابع یک Promise برمیگرداند. آن Promise با رشته fulfilled میشود. اگر تابع خطا بدهد، Promise رد میشود.
نتیجه را بعد از await بخوانید
تابع pour یک Promise میسازد. serve ابتدا waiting را نشان میدهد، سپس منتظر میماند و بعد مقدار lida tea را دریافت میکند.
function pour(order) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
if (order === "") reject("no leaves");
else resolve(order + " tea");
}, 100);
});
}
async function serve() {
console.log("waiting");
let drink = await pour("lida");
console.log(drink);
}
serve();
خروجیها بهترتیب waiting و lida tea هستند. هر دو داخل serve ثبت میشوند، اما خط دوم پس از آمادهشدن نتیجه اجرا میشود.
فراخوان تابع یک Promise میدهد
اگر serve() را بدون await صدا بزنیم، خود نوشیدنی را همان لحظه نمیگیریم.
async function serve() {
return "lida tea";
}
let ticket = serve();
console.log(ticket instanceof Promise);
خروجی true است؛ یعنی ticket یک Promise است. برای خواندن مقدار نهایی باید در تابع async دیگری آن را await کنیم یا از then کمک بگیریم.
مدیریت رد شدن Promise
اگر Promise رد شود، await آن را مانند یک خطا به catch میفرستد. پس عملیاتی را که ممکن است شکست بخورد داخل try قرار دهید.
function pour(order) {
return order === ""
? Promise.reject("no leaves")
: Promise.resolve(order + " tea");
}
async function serveEmpty() {
try {
await pour("");
} catch (reason) {
console.log(reason);
}
}
serveEmpty();
خروجی no leaves است. خطایی که بعد از await و در همان بخش try رخ دهد نیز به همین catch میرسد.
بقیهٔ صفحه به کارش ادامه میدهد
توقف فقط مربوط به اجرای همان تابع async است. خود فراخوانی بلافاصله یک Promise میدهد؛ بنابراین کد همگام بعد از فراخوانی میتواند اجرا شود.
یک نمونهٔ کامل در مرورگر
این صفحه مراحل را داخل یک تابع async ثبت میکند. Promise با یک تایمر کوتاه حل میشود تا نمونه بدون سرور هم مستقل و قابل اجرا باشد.
<!DOCTYPE html>
<html>
<body>
<p id="cup">blank</p>
<p id="line">…</p>
<script>
function pour(order) {
return new Promise(resolve => setTimeout(() => resolve(order + " tea"), 100));
}
async function serve() {
const cup = document.getElementById("cup");
const seen = ["waiting"];
cup.textContent = "waiting";
const drink = await pour("lida");
cup.textContent = drink;
seen.push(drink, "done");
document.getElementById("line").textContent = seen.join(" / ");
}
serve();
</script>
</body>
</html>
خط نهایی waiting / lida tea / done است. مقدار done فقط زمانی اضافه میشود که نتیجهٔ awaited روی صفحه نوشته شده باشد.
تمرین
نام lida را عوض کنید و نتیجه را await کنید. سپس رشتهٔ خالی بدهید و ببینید catch مقدار no leaves را دریافت میکند.
اشتباههای رایج
از فراخوانی تابع async انتظار رشتهٔ آماده نداشته باشید. await را در تابع معمولی ننویسید. همچنین تصور نکنید یک await تمام صفحه را متوقف میکند.
جمعبندی
تابع async همیشه Promise برمیگرداند. await فقط همان تابع را تا مشخصشدن نتیجهٔ Promise نگه میدارد. برای عملیات قابل شکست از try/catch استفاده کنید.
🧠 دانش خود را بیازمایید
دانش خود را بیازمایید
خود را با این آزمون تعاملی به چالش بکشید و ببینید موضوع را چقدر خوب درک کردهاید
📝 دستورالعملها
- هر سوال را با دقت بخوانید
- بهترین پاسخ را برای هر سوال انتخاب کنید
- میتوانید آزمون را هر چند بار که میخواهید تکرار کنید
- پیشرفت شما در بالا نمایش داده میشود