Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are some JavaScript developers using setTimeout for one millisecond? [duplicate]

I have problem when using jQuery plugin tablesorter and I can't call trigger twice.

For example this won't work:

this._$table.trigger('update');
this._$table.trigger('sorton', [[[1,1]]]);

But this works:

this._$table.trigger('update');
setTimeout($.proxy(function() {
    this._$table.trigger('sorton', [[[1,1]]]);
}, this), 1);

And then I see that problem was in trigger 'update', it call method with body:

function () {
    var me = this;
    setTimeout(function () {
        // rebuild parsers.
        me.config.parsers = buildParserCache(
        me, $headers);
        // rebuild the cache map
        cache = buildCache(me);
    }, 1);
}

Why did the tablesorter developer use setTimeout with one millisecond?

like image 212
Dmytro Krasun Avatar asked Aug 21 '12 09:08

Dmytro Krasun


People also ask

Does setTimeout use milliseconds?

Definition and UsageThe setTimeout() method calls a function after a number of milliseconds. 1 second = 1000 milliseconds.

Why do we use setTimeout in JavaScript?

setTimeout is a commonly used function in JavaScript. It sets a timer (a countdown set in milliseconds) for the execution of a callback function, calling the function upon completion of the timer. The setTimeout method can prove handy in various situations.

Is setTimeout accurate?

It's not supposed to be particularly accurate. There are a number of factors limiting how soon the browser can execute the code; quoting from MDN: In addition to "clamping", the timeout can also fire later when the page (or the OS/browser itself) is busy with other tasks.

Does setTimeout repeat?

setTimeout allows us to run a function once after the interval of time. setInterval allows us to run a function repeatedly, starting after the interval of time, then repeating continuously at that interval.


1 Answers

Short asnwer: Function execution queueing

This is the short answer to your question. setTimeout with either 0 or 1 millisecond is used for function execution queueing. Read on to find out why and how.

Javascript has single threaded execution

Javascript engine is a single threaded process. So whenever developers wanted to defer some function execution to get executed right after the current one that's just being executed, a setTimeout is being used to actually queue the next function... It doesn't have anything to do directly with events although functions may be event handlers. The only event in this equation is the timeout event that setTimeout creates.

This is an example of two functions where the first function during its execution queues a second function to be executed right after it.

function first()
{
    // does whatever it needs to

    // something else needs to be executed right afterwards
    setTimeout(second, 1);

    // do some final processing and exit
    return;
}

function second()
{
    // whatever needs to be done
}

So to javascript engine thread the execution queue looks like this:

first()
second()

Mind that this has nothing to do with function call stack.

Why 1ms?

1ms is a very short amount of time, which (almost) assures that your second function will get executed right after your first function returns. You may see sometimes even 0ms which actually executes it right after first function returns.

If one would on the other hand use longer time i.e. 100ms this could result in a different function getting executed in the meantime and that could have an undesired effect on the whole UI process.

Why function queueing in the first place?

Browsers nowadays prevent client side functionality to hang current browser session by observing long running functions. If a particular function runs long enough, browser Javascript execution engine will pause it and ask the user whether they want to terminate it (kill it) or wait for it to complete.

This is usually undesired effect when you actually do have a long running function. For instance imagine you have a function that has to loop through a large number of items processing each one during the process. You definitely don't want the user to terminate the process because the loop needs to execute.

What's the solution in this case? In such case instead of having a single function with loop and executing it, you'd rather have the loop (queueing) function that would then queue function calls for processing each item. This is just an outer skeleton of such functionality.

function queueItems(items) {
    for(var i = 0; i < items.length, i++)
    {
        setTimeout((function(item) {
            return function() {
                processItem(item);
            };
        })(items[i]), 0);
    }
}

function processItem(item) {
    // process individual item
}

This way you'd prevent your functions to run too long and after each executed function control would get back to Javascript engine resetting its function-hang timer. But be aware that while your functions are being executed your UI will likely be unresponsive or at most unpredictable. It may be better to queue your function with some time space in between so UI stays responsive if that's desired.

like image 153
Robert Koritnik Avatar answered Oct 14 '22 02:10

Robert Koritnik