Need4Steed Need4Steed - 1 year ago 99
Javascript Question

How to enforce the execution order of the tasks queued by setTimeout with 0 delay

I need to call some functions sequentially, and in order to force the framework to do a dirty check after each step, I employed setTimeout(func,0) to trigger the dirty check mechanism.

I know simply calling setTimeout one by one won't guarantee the passed async functions would be invoked in expected order, therefore I kludged the following solution:

function foo(arg){
setTimeout(()=>console.log('executing task' + arg),0);
console.log('on call stack' + arg);
return foo;

I tried
, it works fine. But I'm not sure it will always work correctly.

So could anybody please help me with it!

@Steffomio's answer can definitely make the queued task deterministic, it also makes sure that each task has its own event loop ensuing.

Here is my adapted version:

function queueTask(task) {
var queue = [];
function nextTask() {
setTimeout(function () {
queue.length && queue.shift()(); taskCount++;
queue.length && nextTask();
}, 0);
return (function pushTask(task) {
//After the first call trigger the timeout asynchrony
if (queue.length === 1) { nextTask(); }
return pushTask;

//Test part below
function t(arg) { return function () { console.log('Task ' + arg); } }

var taskCount = 0;
var beginTime =;

(function () { console.log(taskCount + ' tasks executed, Time elapsed: ' + ( - beginTime)); });

After some research I learned that the callback passed to
will be called by the system only when the call stack is cleared (no more code on it), thus the actual execution of queued tasks won't start until the the queuing is done, and if we queue several 0-delay timeout tasks linearly, when the next event loop starts, they will all be executed in a single run. That is not what I want! So, calling
inside the callback of the preceding
is the only way so far I know to enforce tick by tick tasks scheduling.

For better understanding, please reference the talk "What the heck is the event loop anyway" given by Philip Roberts at JSConf EU 2014

Answer Source

You need a queue:

q = [];

function queue(){
            console.log('queue: ' + q.shift()); 
            q.length && queue();
        }, 1000);

function addQueue(n){
    return addQueue;

for testing copy and paste code to console.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download