التصريح عن الدوال غير المتزامنة في 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 هذه الميزة.

مصادر ومواصفات