الوحدة Timer في Node.js

من موسوعة حسوب

توفر الوحدة timer واجهة برمجيّة (API) عامة (global) لجدولة (scheduling) الدوال، مما يُمكِّن استدعاءها في فترة مستقبليّة معينة. لا حاجة لاستيراد الوحدة عبر الدالة require('timers')‎‎ لاستخدام الواجهة البرمجيّة؛ وذلك لكون دوال المكتبة عامة.

تصنَع دوال المؤقتات (timers)، في Node.js، واجهة برمجيّة مشابهة لتلك الموجودة في مُتصفحات الويب ولكن باستخدام بنيّة داخليّة مُختلفة مبنيّة اعتمادًا على تقنيّة حلقة الأحداث (Event Loop).

الصنف Immediate

ينشَأ هذا الكائن داخليًا ويُعاد من الدالة ‎setImmediate()‎. يُمكِن تمرير هذا الكائِن إلى الدالة clearImmediate()‎‎ لإلغاء الأحداث المُجدولة.

ستستمر حلقة الأحداث بالعمل، افتراضيًا عند جدولة الكائِن immediate، طالما هذا الكائِن فعّال. يُصدِّر الكائِن Immediate، الذي ترجعه الدالة ‎setImmediate()‎، التابعين immediate.ref()‎‎‎ و ‎immediate.unref()‎ الذين يُمكِن استخدامهما للتحكم بهذا السلوك الافتراضي.

immediate.ref()‎

أُضيفَ في الإصدار 9.7.0

  • القيمة المعادة: الكائِن <Immediate>، مرجع للصنف immediate.

يطلب التابع، عند استدعاءه، استمرار حلقة الأحداث طالما أنَّ الصنف Immediate نشط. لن يُحدِث استدعاء هذا التابع عدّة مرّات أثرًا.

يعمل هذا الصنف، تلقائيًا وافتراضيًا، على جميع الكائِنات من النوع Immediate، ما يعني أنَّه لا ضرورة لاستدعاء التابع Immediate.ref()‎ ما لم يُستدعَ التابع Immediate.unref()‎‎ قبله.

immediate.unref()‎

أُضيفَ في الإصدار 9.7.0

  • القيمة المعادة: الكائِن <Immediate>، مرجع (reference) للصنف immediate.

يسحب التابع، عند استدعاءه، طلبه باستمرار حلقة الأحداث طالما أنَّ الصنف Immediate نشط. قد تتوقف حلقة الأحداث، في حال عدم وجود نشاطات أخرى تتطلَّب استمرار عملها، قبل استدعاء الدالة المقرونة بكائِن المؤقت (المُعامِل callback). لن يُحدِث استدعاء هذا التابع عدّة مرّات أثرًا.

الصنف Timeout

ينشَأ هذا الكائن داخليًا ويُعاد من الدالة setTimeout()‎ و setInterval()‎. يُمكِن تمرير هذا الكائِن إلى الدالة clearTimeout()‎‎ أو clearInterval()‎‎ لإلغاء العمليات المُجدولة. ستستمر حلقة الأحداث بالعمل، افتراضيًا عند جدولة المؤقت بأحد التابعين السالف ذكرهما (setTimeout()‎ و ()setInterval)، طالما أنَّ المؤقِّت نشطٌ. يُصدِّر الكائِن Timeout التابعين timeout.ref()‎‎‎ و timeout.unref()‎ الذين يُمكِن استخدامهما للتحكم بهذا السلوك الافتراضي.

timeout.ref()‎

أُضيفَ في الإصدار 0.9.1

  • القيمة المعادة: الكائِن <Timeout>، مرجِع للصنف timeout.

يطلب التابع، عند استدعاءه، استمرار حلقة الأحداث طالما أنَّ الصنف Timeout نشطٌ. لن يُحدِث استدعاء هذا التابع عدّة مرّات أثرًا.

يعمل هذا الصنف، تلقائيًا وافتراضيًا، على جميع الكائِنات من النوع Timeout، ما يعني أنَّه لا ضرورة لاستدعاء التابع timeout.ref()‎ ما لم يُستدعَ التابع timeout.unref()‎‎ قبله.

timeout.refresh()‎

أُضيفَ في الإصدار 10.2.0

  • القيمة المعادة: الكائِن <Timeout>، مرجِع للصنف timeout.

يُعيّن التابِع وقت بدء المؤقت إلى الوقت الحالي، ويُعيد جدولة المؤقت ليستدعي دالة رد النداء عند حلول وقت البدء الجديد. استخدام هذا التابع مُفيد لاستحداث مؤقت دون الحاجة لحجز كائن JavaScript جديد.

استخدام هذا التابع على مؤقت اُستدعيت الدالة المقرونة به يؤدي إلى إعادة تنشيط المؤقت مرَّة أخرى.

timeout.unref()‎

أُضيفَ في الإصدار 0.9.1

  • القيمة المعادة: الكائِن <Timeout>، مرجع (reference) للصنف timeout.

يسحب التابع، عند استدعاءه، طلبه باستمرار حلقة الأحداث طالما أنَّ الصنف Immediate نشط. قد تتوقف حلقة الأحداث، في حال عدم وجود نشاطات أخرى تتطلَّب استمرار عملها، قبل استدعاء الدالة المقرونة بكائِن المؤقت (المُعامِل callback). لن يُحدِث استدعاء هذا التابع عدّة مرّات أثرًا.

يُنشئ استدعاء التابِع timeout.unref()‎ مؤقتًا داخليًا يُنبِّه حلقة أحداث Node.js. إنشاء الكثير من هذه المُنبِّهات، التي يُنشِئُها استدعاء هذا التابِع، قد يؤثر سلبًا على أداء البرمجيّة.

جدولة المؤقتات

المؤقت في Node.js هو عبارة عن بناء داخلي يستدعي دالة مُمرَّرة له بعض فترة زمنيّة مُعينة. يختلف موعد استدعاء دالة المؤقت بناءً على الطريقة المُستخدمة لإنشاءه والأعمال التي تقوم بها حلقة الأحداث.

setImmediate(callback[, ...args])‎

أُضيفَ في الإصدار 0.9.1

  • callback من النوع <Function>: الدالة التي ستُستدعى في نهاية الدورة الحالية لحلقة الأحداث.
  • args... من النوع <any>: مُعطيات ستُمرَّر للمُعامِل callback عندما يُستدعى (مُعامِل اختياري).

يُجدول التابِع تنفيذ المُعامِل callback بعد تنفيذ أحداث الإدخال والإخراج (I/O events' callbacks) في حلقة الأحداث.

عند استدعاء الدالة setImmediate()‎ عدّة مرَّات، يتم صَف الدوال في المعاملات callback في طابور التنفيذ بالترتيب الذي أُنشِئت به. يُعالَج طابور التنفيذ (الذي يحوي جميع دوال رد النداء) بكامله في كل دورة لحلقة الأحداث. إذا وُجِد مؤقت فوري (immediate timer) بداخل آخر قيد التنفيذ، لن يُنفَّذ حتّى قدوم الدورة التالية من حلقة الأحداث.

سيَصدُر الخطأ TypeError في حال لم تُمرَّر دالة للمُعامِل callback.

يتعامل التابع بطريقة مخصَّصة مع الوعود (promises) المُنشأة بواسطة التابع ()util.promisify:

const util = require('util');
const setImmediatePromise = util.promisify(setImmediate);

setImmediatePromise('foobar').then((value) => {
 // value === 'foobar' (تمرير القيم أمر اختياري)
‎‎// ستُنفَّذ الشيفرة هنا بعد جميع أحداث الإدخال والإخراج
});


‎‎// أو باستخدام الدوال الغير متزامنة
async function timerExample() {
  console.log('Before I/O callbacks');
  await setImmediatePromise();
  console.log('After I/O callbacks');
}
timerExample();

setInterval(callback, delay[, ...args])‎

أُضيفَ في الإصدار 0.0.1

  • callback من النوع <Function>: الدالة التي سيتم استدعاؤها في نهاية الدورة الحالية لحلقة الأحداث.
  • delay من النوع <number>: الفترة الزمنيّة (مُقاسة بالمِلِّي ثانية) الُمنتظرة قبل تنفيذ الدالة المُمرَّرة للمُعامِل callback.
  • args... من النوع <any>: مُعطيات ستُمرَّر للمُعامِل callback عندما يُستدعى (مُعامِل اختياري).

يُجدول التابِع تنفيذ المُعامِل callback بشكل مُتكرِّر كل delay (الفترة الزمنيّة المُمرَّرة للمُعامِل).

تُحال قيمة المُعامِل delay إلى 1 في حال كانت قيمته أكبر من 2147483647 أو أصغر من 1.

سيَصدُر الخطأ TypeError في حال لم تُمرَّر دالة للمُعامِل callback.

setTimeout(callback, delay[, ...args])‎

أُضيفَ في الإصدار 0.0.1

  • callback من النوع <Function>: الدالة التي سيتم استدعاؤها في نهاية الدورة الحالية لحلقة الأحداث.
  • delay من النوع <number>: الفترة الزمنيّة (مُقاسة بالمِلِّي ثانية) الُمنتظرة قبل تنفيذ الدالة المُمرَّرة للمُعامِل callback.
  • args... من النوع <any>: مُعطيات ستُمرَّر للمُعامِل callback عندما يُستدعى (مُعامِل اختياري).

يُجدول التابِع تنفيذ المُعامِل callback مرَّة واحدة بعد مرور delay (الفترة الزمنيّة المُمرَّرة للمُعامِل).

من المُحتمَل ألّا تُستدعى الدالة في الوقت المُحدَّد تمامًا. لا توفر Node.js أيّة ضمانات حول الوقت أو الترتيب الذي تُنفَّذ فيه الدوال. ستُستدعى الدالة المجدولة بأقرب وقت مُمكِن للوقت المُحدَّد.

تُحال قيمة المُعامِل delay إلى 1 في حال كانت قيمته أكبر من 2147483647 أو أصغر من 1.

سيَصدُر الخطأ TypeError في حال لم تُمرَّر دالة للمُعامِل callback.

يتعامل التابع بطريقة مخصَّصة مع الوعود (promises) المُنشأة بواسطة التابع ()util.promisify:

‎‎const util = require('util');
const setTimeoutPromise = util.promisify(setTimeout);

setTimeoutPromise(40, 'foobar').then((value) => {
  // value === 'foobar' (تمرير القيم أمر اختياري)
 ‎‎// ستُنفَّذ الشيفرة هنا بعد حوالي 40 مِلِّي ثانية
});

إلغاء المؤقتات

تعيد كل من التوابع setImmediate()‎‎ و setInterval()‎ و setTimeout()‎‎ كائنًا يُمثِّل مؤقِتًا. يُمكن استخدام هذه الكائنات لإلغاء المؤقت ومنع استدعائه.

لا يُمكِن إلغاء مؤقت أُنشِئ باستخدام نسخة الوعود من ‎‎setImmediate()‎ و ‎setTimeout()‎.

clearImmediate(immediate)‎

أُضيفَ في الإصدار 0.9.1

يُلغي التابِع كائن مؤقِت من النوع Immediate مُنشأ بواسطة التابع setImmediate()‎.

clearInterval(timeout)‎

أُضيفَ في الإصدار 0.0.1

يُلغي التابِع كائن مؤقِت من النوع Timeout مُنشأ بواسطة التابع setInterval()‎.

clearTimeout(timeout)‎

أُضيفَ في الإصدار 0.0.1

يُلغي التابِع كائن مؤقِت من النوع Timeout مُنشأ بواسطة التابع setTimeout()‎.

مصادر