Call setTimeout without delay

后端 未结 5 1001
闹比i
闹比i 2020-12-05 04:07

Quite often see in JavaScript libraries code like this:

setTimeout(function() {
    ...
}, 0);

I would like to know why use such a wrapper

相关标签:
5条回答
  • 2020-12-05 04:33

    Apart from previous answers I'd like to add another useful scenario I can think of: to "escape" from a try-catch block. A setTimeout-delay from within a try-catch block will be executed outside the block and any exception will propagate in the global scope instead.

    Perhaps best example scenario: In today's JavaScript, with the more common use of so called Deferreds/Promises for asynchronous callbacks you are (often) actually running inside a try-catch. Deferreds/Promises wrap the callback in a try-catch to be able to detect and propagate an exception as an error in the async-chain. This is all good for functions that need to be in the chain, but sooner or later you're "done" (i.e fetched all your ajax) and want to run plain non-async code where you Don't want exceptions to be "hidden" anymore. AFAIK Dojo, Kris Kowal's Q, MochiKit and Google Closure lib use try-catch wrapping (Not jQuery though).

    (On couple of odd occasions I've also used the technique to restart singleton-style code without causing recursion. I.e doing a teardown-restart in same loop).

    0 讨论(0)
  • 2020-12-05 04:43

    To allow any previously set timeouts to execute.

    0 讨论(0)
  • 2020-12-05 04:44

    There are a couple of reasons why you would do this

    • There is an action you don't want to run immediately but do want to run at some near future time period.
    • You want to allow other previously registered handlers from a setTimeout or setInterval to run
    0 讨论(0)
  • 2020-12-05 04:55

    Very simplified:

    Browsers are single threaded and this single thread (The UI thread) is shared between the rendering engine and the js engine.

    If the thing you want to do takes alot of time (we talking cycles here but still) it could halt (paus) the rendering (flow and paint).

    In browsers there also exists "The bucket" where all events are first put in wait for the UI thread to be done with whatever it´s doing. As soon as the thread is done it looks in the bucket and picks the task first in line.

    Using setTimeout you create a new task in the bucket after the delay and let the thread deal with it as soon as it´s available for more work.

    A story:

    After 0 ms delay create a new task of the function and put it in the bucket. At that exact moment the UI thread is busy doing something else, and there is another tasks in the bucket already. After 6ms the thread is available and gets the task infront of yours, good, you´re next. But what? That was one huge thing! It has been like foreeeeeever (30ms)!!

    At last, now the thread is done with that and comes and gets your task.

    Most browsers have a minimum delay that is more then 0 so putting 0 as delay means: Put this task in the basket ASAP. But telling the UA to put it in the bucket ASAP is no guarantee it will execute at that moment. The bucket is like the post office, it could be that there is a long queue of other tasks. Post offices are also single threaded with only one person helping all the task... sorry customers with their tasks. Your task has to get in the line as everyone else.

    If the browser doesn´t implement its own ticker, it uses the tick cycles of the OS. Older browsers had minimum delays between 10-15ms. HTML5 specifies that if delay is less then 4ms the UA should increase it to 4ms. This is said to be consistent across browsers released in 2010 and onward.

    See How JavaScript Timers Work by John Resig for more detail.

    Edit: Also see What the heck is the event loop anyway? by Philip Roberts from JSConf EU 2014. This is mandatory viewing for all people touching front-end code.

    0 讨论(0)
  • 2020-12-05 04:56

    When you want to execute rest of your code without waiting previous one to finish you need to add it in anonymous method passed to setTimeout function. Otherwise your code will wait until previous is done

    Example:

    function callMe()
    {
       for(var i = 0; i < 100000; i++)
         {
           document.title = i;
         }
    } 
    
    var x = 10;
    setTimeout(callMe, 0);
    
    var el = document.getElementById('test-id');
    el.innerHTML = 'Im done before callMe method';
    

    That is the reason I use it.

    0 讨论(0)
提交回复
热议问题