How should I “yield” in JavaScript?





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty{ height:90px;width:728px;box-sizing:border-box;
}







2















I am a bit new to modern JavaScript (ES8). What is a preferred way to yield asynchronously, i.e. continue script execution upon some future iterations of the event loop, using await? I saw the following options:



async function yield1() {
await Promise.resolve();
console.log("done");
}

async function yield2() {
// setImmediate is non-standard, only Edge and Node have it
await new Promise(done => (setImmediate? setImmediate: setTimeout)(done));
console.log("done");
}

async function yield3() {
await new Promise(done => setTimeout(done));
console.log("done");
}


Should I chose one after another or they're all the same? Or maybe it depends on the environment (node, browser)?





Updated, was asked in the comments about what I'm trying to achieve. It is a simple observable object that asynchronously fires propertyChanged event when its properties change. Here is a full example, and the "yielding" piece is inside firePropertyChanged:



const EventEmitter = require('events');

class Model extends EventEmitter {
constructor(data) {
super();
this._data = data;
}

get data() {
return this._data;
}

set data(newValue) {
const oldValue = this._data;
if (oldValue !== newValue) {
this._data = newValue;
this.firePropertyChanged('data', newValue, oldValue);
}
}

async firePropertyChanged(property, newValue, oldValue) {
await Promise.resolve().then(() =>
super.emit('propertyChanged', { target: this, property, newValue, oldValue }));
console.log('all propertyChanged handlers have been called asynchronously');
}
}

async function waitForChange(obj) {
await new Promise(resolve =>
obj.once('propertyChanged', args =>
console.log(`propertyChanged: ${args.property}, ${args.oldValue} -> ${args.newValue}`)));
}

async function test() {
const obj = new Model("old");
var change = waitForChange(obj);
console.log(`before change: ${obj.data}`);
obj.data = "new";
console.log(`after change: ${obj.data}`);
await change;
}

test().catch(e => console.error(e));


If you run it with node, the expected output should be:




before change: old
after change: new
propertyChanged: data, old -> new
all propertyChanged handlers have been called asynchronously


The order of this output matters, i.e., I don't want any event handlers for propertyChanged to be invoked before the setter method for data has returned to the caller.










share|improve this question




















  • 2





    Are you aware that setImmediate is not standardised? You might want to discount that one because of that in itself.

    – James Thorpe
    Nov 16 '18 at 11:40











  • @JamesThorpe, no I'm not, thanks for pointing out. It seems to be working across all modern browsers and Node though (IE11 is out of the question).

    – avo
    Nov 16 '18 at 11:42






  • 1





    Interesting - the MDN is listing it as mostly not implemented across the board

    – James Thorpe
    Nov 16 '18 at 11:43






  • 1





    rxjs is a reactive js library. you can create observables which will feel familiar to using generators in say, python. rxjs-dev.firebaseapp.com

    – Joey Gough
    Nov 16 '18 at 11:44











  • @JamesThorpe, you're right! Only Edge and Node have setImmediate. That leaves me with only #1 and #3.

    – avo
    Nov 16 '18 at 11:52


















2















I am a bit new to modern JavaScript (ES8). What is a preferred way to yield asynchronously, i.e. continue script execution upon some future iterations of the event loop, using await? I saw the following options:



async function yield1() {
await Promise.resolve();
console.log("done");
}

async function yield2() {
// setImmediate is non-standard, only Edge and Node have it
await new Promise(done => (setImmediate? setImmediate: setTimeout)(done));
console.log("done");
}

async function yield3() {
await new Promise(done => setTimeout(done));
console.log("done");
}


Should I chose one after another or they're all the same? Or maybe it depends on the environment (node, browser)?





Updated, was asked in the comments about what I'm trying to achieve. It is a simple observable object that asynchronously fires propertyChanged event when its properties change. Here is a full example, and the "yielding" piece is inside firePropertyChanged:



const EventEmitter = require('events');

class Model extends EventEmitter {
constructor(data) {
super();
this._data = data;
}

get data() {
return this._data;
}

set data(newValue) {
const oldValue = this._data;
if (oldValue !== newValue) {
this._data = newValue;
this.firePropertyChanged('data', newValue, oldValue);
}
}

async firePropertyChanged(property, newValue, oldValue) {
await Promise.resolve().then(() =>
super.emit('propertyChanged', { target: this, property, newValue, oldValue }));
console.log('all propertyChanged handlers have been called asynchronously');
}
}

async function waitForChange(obj) {
await new Promise(resolve =>
obj.once('propertyChanged', args =>
console.log(`propertyChanged: ${args.property}, ${args.oldValue} -> ${args.newValue}`)));
}

async function test() {
const obj = new Model("old");
var change = waitForChange(obj);
console.log(`before change: ${obj.data}`);
obj.data = "new";
console.log(`after change: ${obj.data}`);
await change;
}

test().catch(e => console.error(e));


If you run it with node, the expected output should be:




before change: old
after change: new
propertyChanged: data, old -> new
all propertyChanged handlers have been called asynchronously


The order of this output matters, i.e., I don't want any event handlers for propertyChanged to be invoked before the setter method for data has returned to the caller.










share|improve this question




















  • 2





    Are you aware that setImmediate is not standardised? You might want to discount that one because of that in itself.

    – James Thorpe
    Nov 16 '18 at 11:40











  • @JamesThorpe, no I'm not, thanks for pointing out. It seems to be working across all modern browsers and Node though (IE11 is out of the question).

    – avo
    Nov 16 '18 at 11:42






  • 1





    Interesting - the MDN is listing it as mostly not implemented across the board

    – James Thorpe
    Nov 16 '18 at 11:43






  • 1





    rxjs is a reactive js library. you can create observables which will feel familiar to using generators in say, python. rxjs-dev.firebaseapp.com

    – Joey Gough
    Nov 16 '18 at 11:44











  • @JamesThorpe, you're right! Only Edge and Node have setImmediate. That leaves me with only #1 and #3.

    – avo
    Nov 16 '18 at 11:52














2












2








2


2






I am a bit new to modern JavaScript (ES8). What is a preferred way to yield asynchronously, i.e. continue script execution upon some future iterations of the event loop, using await? I saw the following options:



async function yield1() {
await Promise.resolve();
console.log("done");
}

async function yield2() {
// setImmediate is non-standard, only Edge and Node have it
await new Promise(done => (setImmediate? setImmediate: setTimeout)(done));
console.log("done");
}

async function yield3() {
await new Promise(done => setTimeout(done));
console.log("done");
}


Should I chose one after another or they're all the same? Or maybe it depends on the environment (node, browser)?





Updated, was asked in the comments about what I'm trying to achieve. It is a simple observable object that asynchronously fires propertyChanged event when its properties change. Here is a full example, and the "yielding" piece is inside firePropertyChanged:



const EventEmitter = require('events');

class Model extends EventEmitter {
constructor(data) {
super();
this._data = data;
}

get data() {
return this._data;
}

set data(newValue) {
const oldValue = this._data;
if (oldValue !== newValue) {
this._data = newValue;
this.firePropertyChanged('data', newValue, oldValue);
}
}

async firePropertyChanged(property, newValue, oldValue) {
await Promise.resolve().then(() =>
super.emit('propertyChanged', { target: this, property, newValue, oldValue }));
console.log('all propertyChanged handlers have been called asynchronously');
}
}

async function waitForChange(obj) {
await new Promise(resolve =>
obj.once('propertyChanged', args =>
console.log(`propertyChanged: ${args.property}, ${args.oldValue} -> ${args.newValue}`)));
}

async function test() {
const obj = new Model("old");
var change = waitForChange(obj);
console.log(`before change: ${obj.data}`);
obj.data = "new";
console.log(`after change: ${obj.data}`);
await change;
}

test().catch(e => console.error(e));


If you run it with node, the expected output should be:




before change: old
after change: new
propertyChanged: data, old -> new
all propertyChanged handlers have been called asynchronously


The order of this output matters, i.e., I don't want any event handlers for propertyChanged to be invoked before the setter method for data has returned to the caller.










share|improve this question
















I am a bit new to modern JavaScript (ES8). What is a preferred way to yield asynchronously, i.e. continue script execution upon some future iterations of the event loop, using await? I saw the following options:



async function yield1() {
await Promise.resolve();
console.log("done");
}

async function yield2() {
// setImmediate is non-standard, only Edge and Node have it
await new Promise(done => (setImmediate? setImmediate: setTimeout)(done));
console.log("done");
}

async function yield3() {
await new Promise(done => setTimeout(done));
console.log("done");
}


Should I chose one after another or they're all the same? Or maybe it depends on the environment (node, browser)?





Updated, was asked in the comments about what I'm trying to achieve. It is a simple observable object that asynchronously fires propertyChanged event when its properties change. Here is a full example, and the "yielding" piece is inside firePropertyChanged:



const EventEmitter = require('events');

class Model extends EventEmitter {
constructor(data) {
super();
this._data = data;
}

get data() {
return this._data;
}

set data(newValue) {
const oldValue = this._data;
if (oldValue !== newValue) {
this._data = newValue;
this.firePropertyChanged('data', newValue, oldValue);
}
}

async firePropertyChanged(property, newValue, oldValue) {
await Promise.resolve().then(() =>
super.emit('propertyChanged', { target: this, property, newValue, oldValue }));
console.log('all propertyChanged handlers have been called asynchronously');
}
}

async function waitForChange(obj) {
await new Promise(resolve =>
obj.once('propertyChanged', args =>
console.log(`propertyChanged: ${args.property}, ${args.oldValue} -> ${args.newValue}`)));
}

async function test() {
const obj = new Model("old");
var change = waitForChange(obj);
console.log(`before change: ${obj.data}`);
obj.data = "new";
console.log(`after change: ${obj.data}`);
await change;
}

test().catch(e => console.error(e));


If you run it with node, the expected output should be:




before change: old
after change: new
propertyChanged: data, old -> new
all propertyChanged handlers have been called asynchronously


The order of this output matters, i.e., I don't want any event handlers for propertyChanged to be invoked before the setter method for data has returned to the caller.







javascript promise async-await






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 22:41







avo

















asked Nov 16 '18 at 11:35









avoavo

3,18943358




3,18943358








  • 2





    Are you aware that setImmediate is not standardised? You might want to discount that one because of that in itself.

    – James Thorpe
    Nov 16 '18 at 11:40











  • @JamesThorpe, no I'm not, thanks for pointing out. It seems to be working across all modern browsers and Node though (IE11 is out of the question).

    – avo
    Nov 16 '18 at 11:42






  • 1





    Interesting - the MDN is listing it as mostly not implemented across the board

    – James Thorpe
    Nov 16 '18 at 11:43






  • 1





    rxjs is a reactive js library. you can create observables which will feel familiar to using generators in say, python. rxjs-dev.firebaseapp.com

    – Joey Gough
    Nov 16 '18 at 11:44











  • @JamesThorpe, you're right! Only Edge and Node have setImmediate. That leaves me with only #1 and #3.

    – avo
    Nov 16 '18 at 11:52














  • 2





    Are you aware that setImmediate is not standardised? You might want to discount that one because of that in itself.

    – James Thorpe
    Nov 16 '18 at 11:40











  • @JamesThorpe, no I'm not, thanks for pointing out. It seems to be working across all modern browsers and Node though (IE11 is out of the question).

    – avo
    Nov 16 '18 at 11:42






  • 1





    Interesting - the MDN is listing it as mostly not implemented across the board

    – James Thorpe
    Nov 16 '18 at 11:43






  • 1





    rxjs is a reactive js library. you can create observables which will feel familiar to using generators in say, python. rxjs-dev.firebaseapp.com

    – Joey Gough
    Nov 16 '18 at 11:44











  • @JamesThorpe, you're right! Only Edge and Node have setImmediate. That leaves me with only #1 and #3.

    – avo
    Nov 16 '18 at 11:52








2




2





Are you aware that setImmediate is not standardised? You might want to discount that one because of that in itself.

– James Thorpe
Nov 16 '18 at 11:40





Are you aware that setImmediate is not standardised? You might want to discount that one because of that in itself.

– James Thorpe
Nov 16 '18 at 11:40













@JamesThorpe, no I'm not, thanks for pointing out. It seems to be working across all modern browsers and Node though (IE11 is out of the question).

– avo
Nov 16 '18 at 11:42





@JamesThorpe, no I'm not, thanks for pointing out. It seems to be working across all modern browsers and Node though (IE11 is out of the question).

– avo
Nov 16 '18 at 11:42




1




1





Interesting - the MDN is listing it as mostly not implemented across the board

– James Thorpe
Nov 16 '18 at 11:43





Interesting - the MDN is listing it as mostly not implemented across the board

– James Thorpe
Nov 16 '18 at 11:43




1




1





rxjs is a reactive js library. you can create observables which will feel familiar to using generators in say, python. rxjs-dev.firebaseapp.com

– Joey Gough
Nov 16 '18 at 11:44





rxjs is a reactive js library. you can create observables which will feel familiar to using generators in say, python. rxjs-dev.firebaseapp.com

– Joey Gough
Nov 16 '18 at 11:44













@JamesThorpe, you're right! Only Edge and Node have setImmediate. That leaves me with only #1 and #3.

– avo
Nov 16 '18 at 11:52





@JamesThorpe, you're right! Only Edge and Node have setImmediate. That leaves me with only #1 and #3.

– avo
Nov 16 '18 at 11:52












1 Answer
1






active

oldest

votes


















2














OK, I'll address the new summary of your question in your comments (you should probably edit your question to just say this):




I want to run a piece of code on a future iteration of the event loop in the most efficient way (and let the current method return). No particular preferences, but but the order of continuations should matter. E.g., in my example, if property1 changed, then property2 changed, I first want propertyChanged be fired for property1, then for property2 (in both cases, asynchronously to the code that changed both properties).




The short version is you can use pretty much any of the options below to solve your issue. Without knowing more about your specific situations/requirements, I would probably recommend setImmediate() because it can't starve the event queue if triggered recursively, but either process.nextTick() or Promise.resolve().then() will trigger sooner (before other types of events) if that matters to your caller.



Here's some explanation of each choice - each will likely fulfill your objective, but each differs in some details.



All of these options allow the current tick of the event loop to finish and then they schedule a callback to be called on a future tick of the event loop. They differ in exactly when the next callback will be called and some will vary when they schedule the next callback based upon what type of event is currently be processed (e.g. where the event loop is in it's process of scanning several different event queues).



You can start by reading this overview article The Node.js Event Loop, Timers, and process.nextTick()



process.nextTick(cb)



This is the soonest way to schedule the callback. The current tick of the event loop finishes its execution and then before the node.js event loop code looks at any other event queues in the event loop, it looks for items in the nextTickQueue and runs them. Note, it is possible to "starve" the event loop if you are continually calling process.nextTick() recursively because it does not give other events a chance to run until the nextTickQueue is empty. This is not a "fair" scheduler.



enter image description here



setImmediate(cb)



This schedules a callback to be run after the current "phase" of the event loop is finished. You can think of the event loop as cycling through a number of different types of queues. When the current type of queue that is being processed is empty, then any pending setImmediate() callbacks will get processed.



Note, how this relates to other types of events, then depends upon what type of event was processing when setImmediate() was called.



As an example, if you were in the completion callback from fs.read() and you called setImmediate() to schedule a callback, then the event loop would first process any other pending I/O events before processing your setImmediate() callback. Because it doesn't get called until the event loop advances to the next type of event in the event queue, you can't starve the event loop with setImmediate(). Even recursively call setImmediate() will still cycle through all events.



How a pending setTimeout() is processed relative to a setImmediate() that you schedule depends upon what phase of the event loop you were in when you called the setImmediate(). This is generally beyond the scope of what you should be aware of in your code. If relative timing of multiple async operations like this is important, then you are much safer to just write code that guarantees a given sequence regardless of exactly when they operation is enabled by its callback. Promises can help you sequence things like this.



setTimeout(cb, 0)



Timers are one phase of the event loop. As it goes around the event loop looking at different types of event queues, one of the stages is to look for any timer events whose time has passed and thus it is time to call their callback. Because of this timers only run when the event loop is in the "timer phase" so how they fire relative to other types of events is indeterminate. It depends upon where the event loop is in its cycle when the timer is ready to go. Personally, I generally don't use setTimeout(cb, 0) unless I'm trying to synchronize with other timer events as this will guarantee a FIFO order with other timer events, but not with other types of events.



Promise.resolve().then(cb)



To get to this level of detail for promises (which you normally don't need to), you have to be very aware of what the promise implementation you are using is and how it works. A non-native-code promise implementation will use one of the other timing mechanisms to schedule its .then() handlers. Any of them can appropriately meet the Promise specification so they can vary.



Native promises in node.js do have a specific implementation. Personally, I know of no reason why you should write code that depends upon this specific implementation, but lots of people seem to be curious so I'll explain.



You can see a good diagram in this article: Promises, nextTicks and setImmediates. Native promises are implemented using what's called a micro tasks queue. It's essentially another queue like the nextTick queue that is processed after the nextTickQueue, but before any of the other queues. So, queued up .then() or .catch() handlers run immediately after and nextTick calls that are already scheduled and before any other types of events (timers, I/O completion, etc...).



enter image description here



Non-native promise implementations (like Bluebird or Q) don't have the ability to make a new microTasks queue that is processed after the nextTick queue so they use setImmediate() or process.nextTick().






share|improve this answer
























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337067%2fhow-should-i-yield-in-javascript%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    2














    OK, I'll address the new summary of your question in your comments (you should probably edit your question to just say this):




    I want to run a piece of code on a future iteration of the event loop in the most efficient way (and let the current method return). No particular preferences, but but the order of continuations should matter. E.g., in my example, if property1 changed, then property2 changed, I first want propertyChanged be fired for property1, then for property2 (in both cases, asynchronously to the code that changed both properties).




    The short version is you can use pretty much any of the options below to solve your issue. Without knowing more about your specific situations/requirements, I would probably recommend setImmediate() because it can't starve the event queue if triggered recursively, but either process.nextTick() or Promise.resolve().then() will trigger sooner (before other types of events) if that matters to your caller.



    Here's some explanation of each choice - each will likely fulfill your objective, but each differs in some details.



    All of these options allow the current tick of the event loop to finish and then they schedule a callback to be called on a future tick of the event loop. They differ in exactly when the next callback will be called and some will vary when they schedule the next callback based upon what type of event is currently be processed (e.g. where the event loop is in it's process of scanning several different event queues).



    You can start by reading this overview article The Node.js Event Loop, Timers, and process.nextTick()



    process.nextTick(cb)



    This is the soonest way to schedule the callback. The current tick of the event loop finishes its execution and then before the node.js event loop code looks at any other event queues in the event loop, it looks for items in the nextTickQueue and runs them. Note, it is possible to "starve" the event loop if you are continually calling process.nextTick() recursively because it does not give other events a chance to run until the nextTickQueue is empty. This is not a "fair" scheduler.



    enter image description here



    setImmediate(cb)



    This schedules a callback to be run after the current "phase" of the event loop is finished. You can think of the event loop as cycling through a number of different types of queues. When the current type of queue that is being processed is empty, then any pending setImmediate() callbacks will get processed.



    Note, how this relates to other types of events, then depends upon what type of event was processing when setImmediate() was called.



    As an example, if you were in the completion callback from fs.read() and you called setImmediate() to schedule a callback, then the event loop would first process any other pending I/O events before processing your setImmediate() callback. Because it doesn't get called until the event loop advances to the next type of event in the event queue, you can't starve the event loop with setImmediate(). Even recursively call setImmediate() will still cycle through all events.



    How a pending setTimeout() is processed relative to a setImmediate() that you schedule depends upon what phase of the event loop you were in when you called the setImmediate(). This is generally beyond the scope of what you should be aware of in your code. If relative timing of multiple async operations like this is important, then you are much safer to just write code that guarantees a given sequence regardless of exactly when they operation is enabled by its callback. Promises can help you sequence things like this.



    setTimeout(cb, 0)



    Timers are one phase of the event loop. As it goes around the event loop looking at different types of event queues, one of the stages is to look for any timer events whose time has passed and thus it is time to call their callback. Because of this timers only run when the event loop is in the "timer phase" so how they fire relative to other types of events is indeterminate. It depends upon where the event loop is in its cycle when the timer is ready to go. Personally, I generally don't use setTimeout(cb, 0) unless I'm trying to synchronize with other timer events as this will guarantee a FIFO order with other timer events, but not with other types of events.



    Promise.resolve().then(cb)



    To get to this level of detail for promises (which you normally don't need to), you have to be very aware of what the promise implementation you are using is and how it works. A non-native-code promise implementation will use one of the other timing mechanisms to schedule its .then() handlers. Any of them can appropriately meet the Promise specification so they can vary.



    Native promises in node.js do have a specific implementation. Personally, I know of no reason why you should write code that depends upon this specific implementation, but lots of people seem to be curious so I'll explain.



    You can see a good diagram in this article: Promises, nextTicks and setImmediates. Native promises are implemented using what's called a micro tasks queue. It's essentially another queue like the nextTick queue that is processed after the nextTickQueue, but before any of the other queues. So, queued up .then() or .catch() handlers run immediately after and nextTick calls that are already scheduled and before any other types of events (timers, I/O completion, etc...).



    enter image description here



    Non-native promise implementations (like Bluebird or Q) don't have the ability to make a new microTasks queue that is processed after the nextTick queue so they use setImmediate() or process.nextTick().






    share|improve this answer




























      2














      OK, I'll address the new summary of your question in your comments (you should probably edit your question to just say this):




      I want to run a piece of code on a future iteration of the event loop in the most efficient way (and let the current method return). No particular preferences, but but the order of continuations should matter. E.g., in my example, if property1 changed, then property2 changed, I first want propertyChanged be fired for property1, then for property2 (in both cases, asynchronously to the code that changed both properties).




      The short version is you can use pretty much any of the options below to solve your issue. Without knowing more about your specific situations/requirements, I would probably recommend setImmediate() because it can't starve the event queue if triggered recursively, but either process.nextTick() or Promise.resolve().then() will trigger sooner (before other types of events) if that matters to your caller.



      Here's some explanation of each choice - each will likely fulfill your objective, but each differs in some details.



      All of these options allow the current tick of the event loop to finish and then they schedule a callback to be called on a future tick of the event loop. They differ in exactly when the next callback will be called and some will vary when they schedule the next callback based upon what type of event is currently be processed (e.g. where the event loop is in it's process of scanning several different event queues).



      You can start by reading this overview article The Node.js Event Loop, Timers, and process.nextTick()



      process.nextTick(cb)



      This is the soonest way to schedule the callback. The current tick of the event loop finishes its execution and then before the node.js event loop code looks at any other event queues in the event loop, it looks for items in the nextTickQueue and runs them. Note, it is possible to "starve" the event loop if you are continually calling process.nextTick() recursively because it does not give other events a chance to run until the nextTickQueue is empty. This is not a "fair" scheduler.



      enter image description here



      setImmediate(cb)



      This schedules a callback to be run after the current "phase" of the event loop is finished. You can think of the event loop as cycling through a number of different types of queues. When the current type of queue that is being processed is empty, then any pending setImmediate() callbacks will get processed.



      Note, how this relates to other types of events, then depends upon what type of event was processing when setImmediate() was called.



      As an example, if you were in the completion callback from fs.read() and you called setImmediate() to schedule a callback, then the event loop would first process any other pending I/O events before processing your setImmediate() callback. Because it doesn't get called until the event loop advances to the next type of event in the event queue, you can't starve the event loop with setImmediate(). Even recursively call setImmediate() will still cycle through all events.



      How a pending setTimeout() is processed relative to a setImmediate() that you schedule depends upon what phase of the event loop you were in when you called the setImmediate(). This is generally beyond the scope of what you should be aware of in your code. If relative timing of multiple async operations like this is important, then you are much safer to just write code that guarantees a given sequence regardless of exactly when they operation is enabled by its callback. Promises can help you sequence things like this.



      setTimeout(cb, 0)



      Timers are one phase of the event loop. As it goes around the event loop looking at different types of event queues, one of the stages is to look for any timer events whose time has passed and thus it is time to call their callback. Because of this timers only run when the event loop is in the "timer phase" so how they fire relative to other types of events is indeterminate. It depends upon where the event loop is in its cycle when the timer is ready to go. Personally, I generally don't use setTimeout(cb, 0) unless I'm trying to synchronize with other timer events as this will guarantee a FIFO order with other timer events, but not with other types of events.



      Promise.resolve().then(cb)



      To get to this level of detail for promises (which you normally don't need to), you have to be very aware of what the promise implementation you are using is and how it works. A non-native-code promise implementation will use one of the other timing mechanisms to schedule its .then() handlers. Any of them can appropriately meet the Promise specification so they can vary.



      Native promises in node.js do have a specific implementation. Personally, I know of no reason why you should write code that depends upon this specific implementation, but lots of people seem to be curious so I'll explain.



      You can see a good diagram in this article: Promises, nextTicks and setImmediates. Native promises are implemented using what's called a micro tasks queue. It's essentially another queue like the nextTick queue that is processed after the nextTickQueue, but before any of the other queues. So, queued up .then() or .catch() handlers run immediately after and nextTick calls that are already scheduled and before any other types of events (timers, I/O completion, etc...).



      enter image description here



      Non-native promise implementations (like Bluebird or Q) don't have the ability to make a new microTasks queue that is processed after the nextTick queue so they use setImmediate() or process.nextTick().






      share|improve this answer


























        2












        2








        2







        OK, I'll address the new summary of your question in your comments (you should probably edit your question to just say this):




        I want to run a piece of code on a future iteration of the event loop in the most efficient way (and let the current method return). No particular preferences, but but the order of continuations should matter. E.g., in my example, if property1 changed, then property2 changed, I first want propertyChanged be fired for property1, then for property2 (in both cases, asynchronously to the code that changed both properties).




        The short version is you can use pretty much any of the options below to solve your issue. Without knowing more about your specific situations/requirements, I would probably recommend setImmediate() because it can't starve the event queue if triggered recursively, but either process.nextTick() or Promise.resolve().then() will trigger sooner (before other types of events) if that matters to your caller.



        Here's some explanation of each choice - each will likely fulfill your objective, but each differs in some details.



        All of these options allow the current tick of the event loop to finish and then they schedule a callback to be called on a future tick of the event loop. They differ in exactly when the next callback will be called and some will vary when they schedule the next callback based upon what type of event is currently be processed (e.g. where the event loop is in it's process of scanning several different event queues).



        You can start by reading this overview article The Node.js Event Loop, Timers, and process.nextTick()



        process.nextTick(cb)



        This is the soonest way to schedule the callback. The current tick of the event loop finishes its execution and then before the node.js event loop code looks at any other event queues in the event loop, it looks for items in the nextTickQueue and runs them. Note, it is possible to "starve" the event loop if you are continually calling process.nextTick() recursively because it does not give other events a chance to run until the nextTickQueue is empty. This is not a "fair" scheduler.



        enter image description here



        setImmediate(cb)



        This schedules a callback to be run after the current "phase" of the event loop is finished. You can think of the event loop as cycling through a number of different types of queues. When the current type of queue that is being processed is empty, then any pending setImmediate() callbacks will get processed.



        Note, how this relates to other types of events, then depends upon what type of event was processing when setImmediate() was called.



        As an example, if you were in the completion callback from fs.read() and you called setImmediate() to schedule a callback, then the event loop would first process any other pending I/O events before processing your setImmediate() callback. Because it doesn't get called until the event loop advances to the next type of event in the event queue, you can't starve the event loop with setImmediate(). Even recursively call setImmediate() will still cycle through all events.



        How a pending setTimeout() is processed relative to a setImmediate() that you schedule depends upon what phase of the event loop you were in when you called the setImmediate(). This is generally beyond the scope of what you should be aware of in your code. If relative timing of multiple async operations like this is important, then you are much safer to just write code that guarantees a given sequence regardless of exactly when they operation is enabled by its callback. Promises can help you sequence things like this.



        setTimeout(cb, 0)



        Timers are one phase of the event loop. As it goes around the event loop looking at different types of event queues, one of the stages is to look for any timer events whose time has passed and thus it is time to call their callback. Because of this timers only run when the event loop is in the "timer phase" so how they fire relative to other types of events is indeterminate. It depends upon where the event loop is in its cycle when the timer is ready to go. Personally, I generally don't use setTimeout(cb, 0) unless I'm trying to synchronize with other timer events as this will guarantee a FIFO order with other timer events, but not with other types of events.



        Promise.resolve().then(cb)



        To get to this level of detail for promises (which you normally don't need to), you have to be very aware of what the promise implementation you are using is and how it works. A non-native-code promise implementation will use one of the other timing mechanisms to schedule its .then() handlers. Any of them can appropriately meet the Promise specification so they can vary.



        Native promises in node.js do have a specific implementation. Personally, I know of no reason why you should write code that depends upon this specific implementation, but lots of people seem to be curious so I'll explain.



        You can see a good diagram in this article: Promises, nextTicks and setImmediates. Native promises are implemented using what's called a micro tasks queue. It's essentially another queue like the nextTick queue that is processed after the nextTickQueue, but before any of the other queues. So, queued up .then() or .catch() handlers run immediately after and nextTick calls that are already scheduled and before any other types of events (timers, I/O completion, etc...).



        enter image description here



        Non-native promise implementations (like Bluebird or Q) don't have the ability to make a new microTasks queue that is processed after the nextTick queue so they use setImmediate() or process.nextTick().






        share|improve this answer













        OK, I'll address the new summary of your question in your comments (you should probably edit your question to just say this):




        I want to run a piece of code on a future iteration of the event loop in the most efficient way (and let the current method return). No particular preferences, but but the order of continuations should matter. E.g., in my example, if property1 changed, then property2 changed, I first want propertyChanged be fired for property1, then for property2 (in both cases, asynchronously to the code that changed both properties).




        The short version is you can use pretty much any of the options below to solve your issue. Without knowing more about your specific situations/requirements, I would probably recommend setImmediate() because it can't starve the event queue if triggered recursively, but either process.nextTick() or Promise.resolve().then() will trigger sooner (before other types of events) if that matters to your caller.



        Here's some explanation of each choice - each will likely fulfill your objective, but each differs in some details.



        All of these options allow the current tick of the event loop to finish and then they schedule a callback to be called on a future tick of the event loop. They differ in exactly when the next callback will be called and some will vary when they schedule the next callback based upon what type of event is currently be processed (e.g. where the event loop is in it's process of scanning several different event queues).



        You can start by reading this overview article The Node.js Event Loop, Timers, and process.nextTick()



        process.nextTick(cb)



        This is the soonest way to schedule the callback. The current tick of the event loop finishes its execution and then before the node.js event loop code looks at any other event queues in the event loop, it looks for items in the nextTickQueue and runs them. Note, it is possible to "starve" the event loop if you are continually calling process.nextTick() recursively because it does not give other events a chance to run until the nextTickQueue is empty. This is not a "fair" scheduler.



        enter image description here



        setImmediate(cb)



        This schedules a callback to be run after the current "phase" of the event loop is finished. You can think of the event loop as cycling through a number of different types of queues. When the current type of queue that is being processed is empty, then any pending setImmediate() callbacks will get processed.



        Note, how this relates to other types of events, then depends upon what type of event was processing when setImmediate() was called.



        As an example, if you were in the completion callback from fs.read() and you called setImmediate() to schedule a callback, then the event loop would first process any other pending I/O events before processing your setImmediate() callback. Because it doesn't get called until the event loop advances to the next type of event in the event queue, you can't starve the event loop with setImmediate(). Even recursively call setImmediate() will still cycle through all events.



        How a pending setTimeout() is processed relative to a setImmediate() that you schedule depends upon what phase of the event loop you were in when you called the setImmediate(). This is generally beyond the scope of what you should be aware of in your code. If relative timing of multiple async operations like this is important, then you are much safer to just write code that guarantees a given sequence regardless of exactly when they operation is enabled by its callback. Promises can help you sequence things like this.



        setTimeout(cb, 0)



        Timers are one phase of the event loop. As it goes around the event loop looking at different types of event queues, one of the stages is to look for any timer events whose time has passed and thus it is time to call their callback. Because of this timers only run when the event loop is in the "timer phase" so how they fire relative to other types of events is indeterminate. It depends upon where the event loop is in its cycle when the timer is ready to go. Personally, I generally don't use setTimeout(cb, 0) unless I'm trying to synchronize with other timer events as this will guarantee a FIFO order with other timer events, but not with other types of events.



        Promise.resolve().then(cb)



        To get to this level of detail for promises (which you normally don't need to), you have to be very aware of what the promise implementation you are using is and how it works. A non-native-code promise implementation will use one of the other timing mechanisms to schedule its .then() handlers. Any of them can appropriately meet the Promise specification so they can vary.



        Native promises in node.js do have a specific implementation. Personally, I know of no reason why you should write code that depends upon this specific implementation, but lots of people seem to be curious so I'll explain.



        You can see a good diagram in this article: Promises, nextTicks and setImmediates. Native promises are implemented using what's called a micro tasks queue. It's essentially another queue like the nextTick queue that is processed after the nextTickQueue, but before any of the other queues. So, queued up .then() or .catch() handlers run immediately after and nextTick calls that are already scheduled and before any other types of events (timers, I/O completion, etc...).



        enter image description here



        Non-native promise implementations (like Bluebird or Q) don't have the ability to make a new microTasks queue that is processed after the nextTick queue so they use setImmediate() or process.nextTick().







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 22 '18 at 4:35









        jfriend00jfriend00

        442k55581624




        442k55581624
































            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53337067%2fhow-should-i-yield-in-javascript%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Florida Star v. B. J. F.

            Danny Elfman

            Lugert, Oklahoma