التصريح عن الدوال غير المتزامنة في JavaScript
التصريح عن دالة غير متزامنة (asynchronous function declaration) يُعيد كائنًا من النوع AsyncFunction
، يمكن أيضًا إنشاء الدوال غير المتزامنة عبر تعابير تعريف الدوال غير المتزامنة (async function expression
).
البنية العامة
async function name([param[, param[, ... param]]]) {
statements
}
name
اسم الدالة
param
اسم الوسيط المُرَّر إلى الدالة.
statements
التعابير البرمجية التي تُشكِّل جسم الدالة.
القيمة المعادة
كائن AsyncFunction
الذي يُمثِّل الدالة غير المتزامنة ويُنفِّذ الشيفرة الموجودة ضمنها.
الوصف
عندما تُستدعى دالة غير متزامنة، فستعيد كائن Promise
، وعندما تُعيد دالةٌ غير متزامنةٍ قيمةً فستُستبين (resolve) قيمة «الوعد» (أي الكائن Promise
)، وعندما ترمي دالةٌ غيرُ متزامنةٍ استثناءً فسيُرفَض الوعد (أي الكائن Promise
).
يمكن أن تحتوي الدوال غير المتزامنة على التعبير await
، الذي يوقف تنفيذ الدالة غير المتزامنة وينتظر استبيان قيمة الوعد (الكائن Promise
) ثم يُكمِل تنفيذ الدالة غير المتزامنة ويُعيد القيمة المُستبينة (resolved value).
الغرض من دوال async
/await
هو تبسيط استخدام الوعود (promises) بشكل متزامن (synchronously) ولتنفيذ سلوك معيّن على مجموعة من الوعود (كائنات Promises
).
أمثلة
مثال بسيط
function resolveAfter2Seconds(x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function add1(x) {
const a = await resolveAfter2Seconds(20);
const b = await resolveAfter2Seconds(30);
return x + a + b;
}
add1(10).then(v => {
console.log(v); // إظهار 60 بعد 4 ثواني
});
async function add2(x) {
const p_a = resolveAfter2Seconds(20);
const p_b = resolveAfter2Seconds(30);
return x + await p_a + await p_b;
}
add2(10).then(v => {
console.log(v); // إظهار 60 بعد 2 ثواني
});
لاحظ أنَّ التنفيذ قد توقف لمدة ثانيتن في الدالة add1
لأوّل await
وثم توقف لثانيتن أخرتين لثاني await
؛ ذلك لأنَّ المؤقت الثاني لم يُنشَأ حتى انتهى تنفيذ الأول. لكن في الدالة add2
فقد أُنشِئ كلا المؤقتين معًا وثم انتظرناهما (await
) معًا؛ وهذا أدى إلى تنفيذ الدالة في ثانيتين بدلًا من 4 ثواني، وذلك لأنَّ المؤقتين يعملان في وقتٍ واحد؛ لكن لاحظ أنَّ استدعائَيّ await
سيعملان بالتسلسل وليس بالتوازي: أي أنَّ هذا ليس تطبيقًا تلقائيًا لاستخدام Promise.all
، فإذا أردتَ انتظار await
وعدَين (promises) أو أكثر على التوازي، فيجب أن تستخدم Promise.all
.
إعادة كتابة سلسلة وعود باستخدام دالة غير متزامنة
أيّة واجهة برمجية (API) تُعيد كائن Promise
ستؤدي إلى إنشاء سلسلة وعود، وهي تُقسِّم الدالة إلى أقسام عديدة. انظر إلى الشيفرة الآتية:
function getProcessedData(url) {
return downloadData(url) // إعادة وعد
.catch(e => {
return downloadFallbackData(url) // إعادة وعد
})
.then(v => {
return processDataInWorker(v); // إعادة وعد
});
}
يمكن كتابة ما سبق كما يلي باستخدام دالة غير متزامنة:
async function getProcessedData(url) {
let v;
try {
v = await downloadData(url);
} catch(e) {
v = await downloadFallbackData(url);
}
return processDataInWorker(v);
}
لاحظ عدم وجود التعبير await
في المثال السابق على التعبير البرمجي return
، وذلك لأنَّ القيمة المُعادة من الدالة غير المتزامنة (async function) ستحتوى ضمنيًا في Promise.resolve
.
دعم المتصفحات
الميزة | Chrome | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
الدعم الأساسي | 55 | 52 | غير مدعومة | 42 | 10.1 |
على النقيض من متصفح IE، يدعم متصفح Edge هذه الميزة.
مصادر ومواصفات
- مسودة المعيار ECMAScript Latest Draft.
- معيار ECMAScript 2017.