Skip to content

فهم setImmediate()

عندما تريد تنفيذ جزء من التعليمات البرمجية بشكل غير متزامن، ولكن في أقرب وقت ممكن، فإن أحد الخيارات هو استخدام دالة setImmediate() التي يوفرها Node.js:

js
setImmediate(() => {
    // القيام بشيء ما
})

أي دالة تُمرر كحجة لـ setImmediate() هي دالة استدعاء تُنفذ في التكرار التالي لحلقة الأحداث.

ما هو الفرق بين setImmediate() و setTimeout(() => {}, 0) (تمرير مهلة 0 مللي ثانية)، و process.nextTick() و Promise.then()؟

ستُنفذ الدالة المُمررة إلى process.nextTick() في التكرار الحالي لحلقة الأحداث، بعد انتهاء العملية الحالية. وهذا يعني أنها ستُنفذ دائمًا قبل setTimeout و setImmediate.

دالة الاستدعاء setTimeout() مع تأخير 0 مللي ثانية مشابهة جدًا لـ setImmediate(). سيعتمد ترتيب التنفيذ على عوامل مختلفة، لكن كلاهما سيتم تشغيلهما في التكرار التالي لحلقة الأحداث.

تُضاف دالة الاستدعاء process.nextTick إلى مكدس process.nextTick. وتُضاف دالة الاستدعاء Promise.then() إلى مكدس المهام الدقيقة للوعود. وتُضاف دالة الاستدعاء setTimeout، setImmediate إلى مكدس المهام الكبيرة.

تنفذ حلقة الأحداث المهام في مكدس process.nextTick أولاً، ثم تنفذ مكدس المهام الدقيقة للوعود، ثم تنفذ setTimeout أو setImmediate مكدس المهام الكبيرة.

فيما يلي مثال لإظهار الترتيب بين setImmediate()، و process.nextTick()، و Promise.then():

js
const baz = () => console.log('baz');
const foo = () => console.log('foo');
const zoo = () => console.log('zoo');
const start = () => {
  console.log('start');
  setImmediate(baz);
  new Promise((resolve, reject) => {
    resolve('bar');
  }).then(resolve => {
    console.log(resolve);
    process.nextTick(zoo);
  });
  process.nextTick(foo);
};
start();
// start foo bar zoo baz

سوف تقوم هذه الكود أولاً باستدعاء start()، ثم استدعاء foo() في مكدس process.nextTick. بعد ذلك، سيعالج مكدس المهام الدقيقة للوعود، الذي يُطبع bar ويضيف zoo() في مكدس process.nextTick في نفس الوقت. ثم سيتصل بـ zoo() الذي تم إضافته للتو. في النهاية، يتم استدعاء baz() في مكدس المهام الكبيرة.

المبدأ المذكور أعلاه صحيح في حالات CommonJS، ولكن ضع في اعتبارك في وحدات ES، مثل ملفات mjs، سيكون ترتيب التنفيذ مختلفًا:

js
// start bar foo zoo baz

هذا لأن وحدة ES التي يتم تحميلها مُغلّفة كعملية غير متزامنة، وبالتالي فإن البرنامج النصي بأكمله موجود بالفعل في مكدس المهام الدقيقة للوعود. لذلك عندما يتم حل الوعد على الفور، يتم إضافة دالة الاستدعاء الخاصة به إلى مكدس المهام الدقيقة. سيحاول Node.js مسح المكدس قبل الانتقال إلى أي مكدس آخر، وبالتالي سترى أنه يُخرج bar أولاً.