it-swarm.asia

nextTick مقابل setImmediate ، التفسير البصري

أنا في حيرة من أمري حول الاختلافات بين nextTick و setImmediate. لقد قرأت جميع الوثائق المتعلقة بها على شبكة الإنترنت ولكن ما زلت لا أفهم كيف تعمل.

أمثلة:

function log(n) { console.log(n); }

setImmediate

setImmediate(function() {
  setImmediate(function() {
    log(1);
    setImmediate(function() { log(2); });
    setImmediate(function() { log(3); });
  });
  setImmediate(function() {
    log(4);
    setImmediate(function() { log(5); });
    setImmediate(function() { log(6); });
  });
});

//1 2 3 4 5 6

nextTick

process.nextTick(function() {
  process.nextTick(function() {
    log(1);
    process.nextTick(function() { log(2); });
    process.nextTick(function() { log(3); });
  });
  process.nextTick(function() {
    log(4);
    process.nextTick(function() { log(5); });
    process.nextTick(function() { log(6); });
  });
});

//1 4 2 3 5 6

لماذا هذه النتائج؟ يرجى توضيح مع شرح بصري أو من السهل جدا متابعة التفسير. حتى العقدة الأساسية devs لا تتفق على كيفية فهم nextTick و setImmediate.

مصادر:

86
Gabriel Llamas

النظر في المثالان:

setImmediate

setImmediate(function A() {
  setImmediate(function B() {
    log(1);
    setImmediate(function D() { log(2); });
    setImmediate(function E() { log(3); });
  });
  setImmediate(function C() {
    log(4);
    setImmediate(function F() { log(5); });
    setImmediate(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 'TIMEOUT FIRED' 1 4 2 3 5 6
// OR
// 1 'TIMEOUT FIRED' 4 2 3 5 6

nextTick

process.nextTick(function A() {
  process.nextTick(function B() {
    log(1);
    process.nextTick(function D() { log(2); });
    process.nextTick(function E() { log(3); });
  });
  process.nextTick(function C() {
    log(4);
    process.nextTick(function F() { log(5); });
    process.nextTick(function G() { log(6); });
  });
});

setTimeout(function timeout() {
  console.log('TIMEOUT FIRED');
}, 0)

// 1 4 2 3 5 6 'TIMEOUT FIRED'

يتم إطلاق عمليات الاسترجاعات setImmediate من حلقة الحدث ، مرة واحدة في التكرار بالترتيب الذي تم وضعها في قائمة الانتظار. لذلك في التكرار الأول من حلقة الحدث ، يتم تشغيل رد الاتصال A. ثم في التكرار الثاني من حلقة الحدث ، يتم تشغيل رد الاتصال B ، ثم يتم إيقاف رد الاتصال C في حلقة الحدث الثالثة ، وما إلى ذلك ، مما يمنع حلقة الحدث من حظرها ويسمح بردود الإدخال/الإخراج الأخرى إلى يسمى في الوقت المتوسط ​​(كما هو الحال في مهلة 0ms ، التي يتم تشغيلها على تكرار الحلقة الأولى أو الثانية).

ومع ذلك ، يتم دائمًا إطلاق عمليات الاسترجاعات التالية في الحال بعد تنفيذ التعليمات البرمجية الحالية وقبل العودة إلى حلقة الأحداث. في مثال nextTick ، ​​ينتهي بنا الأمر إلى تنفيذ جميع عمليات الاسترجاعات التالية التالية قبل العودة إلى حلقة الأحداث. نظرًا لأنه سيتم استدعاء رد الاتصال الخاص بـ setTimeout من حلقة الحدث ، لن يتم إخراج النص "TIMEOUT FIRED" حتى يتم الانتهاء من كل مرة يتم فيها معاودة الاتصال.

100
Dave Stibrany

وفقًا لأسماء مستندات Node.js الخاصة بهذه الدالتين يتم تبديلها تمامًا

setImmediate () ( الأفضل الموصى به )

يتم إطلاقه أولاً في قائمة انتظار الأحداث


process.nextTick () ( استخدام الحالات الخاصة ، انظر المثال لاحقًا على )

انها النار على الفور ، انها kinda كتابة بيان أكثر في النهاية في الملف الحالي


إذا كان لدينا هذا الرمز

setTimeout(function(){
  console.log('Hello world 5'); // It's waiting like a normal person at a queue
}, 0);

setImmediate(function(){
  console.log('Hello world 4'); 
  // It's like get to last and be take care of first 
  // but always after of .nextTick and before of setInterval(, 0)
});

process.nextTick(function(){
   console.log('Hello world 3'); // It's like be at the bottom at this file
});

console.log('Hello world 1');
console.log('Hello world 2');

شرح مرئي حسب طلبك:

enter image description here

حالات للاستخدام process.nextTick () عندما يتعين عليك إطلاقها والحدث قبل معالجتها:

const EventEmitter = require('events');
const util = require('util');

function MyEmitter() {
  EventEmitter.call(this);

  // use nextTick to emit the event once a handler is assigned
  process.nextTick(function () {
    this.emit('event');
  }.bind(this));
}
util.inherits(MyEmitter, EventEmitter);

const myEmitter = new MyEmitter();
myEmitter.on('event', function() {
  console.log('an event occurred!');
});

انظر إلى هذا الفيديو حيث فيليب روبرتس يعطينا شرحًا رائعًا عن حلقة حدث وقت التشغيل ونظر إلى مصحح أخطاء الأحداث عبر الإنترنت اختبار حي كيف تعمل حلقة الحدث

المصدر: https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate

23
gsalgadotoledo

لا يمكنني إعادة إنتاج نتائجك لـ setImmediate. يجب أن يكون هو نفسه nextTick (وهو في اختباراتي) لأنهم في هذه الحالة يفعلون نفس الشيء إلى حد كبير. التفسير الوحيد المعقول لذلك هو أن setImmediate متزامن إلى حد ما ، لكنه ليس كذلك.

ووفقًا لـ وثائق NodeJS والفرق الحقيقي الوحيد هو أن عدة nextTick قد تطلق في تكرار حلقة واحدة (اعتمادًا على maxTickDepth) ، بينما يتم إطلاق setImmediate مرة واحدة لكل تكرار.

8
freakish

أدناه يعطيك وضوح أفضل.

setImmediate

  1. يتم تنفيذ البرنامج النصي بمجرد اكتمال مرحلة الاستطلاع الحالية.
  2. إنها وظيفة وحدة مؤقت وجهاز مؤقت وظائف ، يمكنك الاتصال بهم دون require.
  3. يمكن مسح بواسطة clearImmediate ().
  4. عيّن التنفيذ "الفوري" لرد الاتصال بعد عمليات رد الفعل لأحداث الإدخال/الإخراج قبل setTimeout () و setInterval ().

nextTick

  1. إنها دالة كائن عمومي عملية من NodeJS.
  2. سيتم حل جميع عمليات الاسترجاعات التي تم تمريرها إلى process.nextTick () قبل متابعة حلقة الحدث.
  3. السماح للمستخدمين بمعالجة الأخطاء.
  4. يساعد في محاولة الطلب مرة أخرى قبل أن تستمر حلقة الأحداث.

مقتطف رمز بسيط.

console.log("I'm First");

setImmediate(function () {
  console.log('Im setImmediate');
});

console.log("I'm Second");

process.nextTick(function () {
  console.log('Im nextTick');
});

console.log("I'm Last");

/*
Output
$ node server.js
I'm First
I'm Second
I'm Last
Im nextTick
Im setImmediate
*/
3
Venkat.R

أعتقد أن جميع الإجابات الواردة أعلاه عفا عليها الزمن ، لأنني حصلت على إجابات مختلفة باستمرار مع الإصدار الحالي من nodejs ومن السهل التفكير حول

var log=console.log
log(process.version)

var makeAsyncCall
if(false)
    makeAsyncCall=setImmediate
else
    makeAsyncCall=process.nextTick;

makeAsyncCall(function A () {
    makeAsyncCall(function B() {
        log(1);
        makeAsyncCall(function C() { log(2); });
        makeAsyncCall(function D() { log(3); });
    });
    makeAsyncCall(function E() {
        log(4);
        makeAsyncCall(function F() { log(5); });
        makeAsyncCall(function G() { log(6); });
    });
});
//1
//4
//2
//3
//5
//6
//in both case

بعد القراءة https://github.com/nodejs/node/blob/master/doc/topics/the-event-loop-timers-and-nexttick.md#processnexttick-vs-setimmediate دعنا نبدأ من setImmediate ، يجب أن نتعقب رمز check queue لأنه هو المكان الذي يوجد به رد الاتصال setImmediate.

التكرار الأول

A هو Push to check queue

قائمة انتظار التحقق: [A]

التكرار الثاني

A يتم سحبها من queue للتنفيذ

أثناء تنفيذه ، وضع B و E على queue ثم ، A أكمل وابدأ التكرار التالي

قائمة انتظار التحقق: [B، E]

التكرار الثالث

اسحب B وادفع CD

قائمة انتظار التحقق: [E ، C ، D]

التكرار الرابع

اسحب E وادفع FG

قائمة انتظار التحقق: [C ، D ، F ، G]

وأخيرا

تنفيذ عمليات الاسترجاعات في قائمة الانتظار بالتسلسل

بالنسبة لحالة nextTick ، تعمل قائمة الانتظار بنفس الطريقة تمامًا ، ولهذا تنتج النتيجة نفسها

الاختلاف هو:

ستتم معالجة theTickQueue التالي بعد اكتمال العملية الحالية ، بغض النظر عن المرحلة الحالية من حلقة الحدث

لتوضيح الأمر ، تحتفظ حلقة الحدث بقوائم انتظار متعددة و check queue هي واحدة منها فقط ، ستقرر العقدة قائمة الانتظار التي سيتم استخدامها بناءً على بعض القواعد

مع process.nextTick ومع ذلك ، فإنه نوع من تجاوز كل القاعدة وتنفيذ رد الاتصال في nextTick على الفور

2
Guichi