26914


[lodashのdefer](https://lodash.com/docs#defer)の説明を見ると、以下のように書いてあります。

> Defers invoking the func until the current call stack has cleared.

私は、同じ目的で次のようなコードを書くことがあります。

[code]

    setTimeout(function () {
        /* 今の一連の処理が完了するまで遅延させたい処理 */
    }, 0);
    
[/code]

これと同じだろうと思ってlodashのコードを見てみると、第二引数には`1`を渡していました。  
なぜ`0`ではなくあえて`1`を指定するのでしょうか？  
もしかすると、`0`では遅延させられない（現在実行中の処理をブロックして実行してしまう）可能性がありますか？


CC BY-SA 3.0
2016-06-21T04:45:40.350
26909
2016-06-21T07:32:36.943
8078
question
javascript
setTimeout(func, 0) の仕様


> なぜ0ではなくあえて1を指定するのでしょうか？

lodashやUnderscore.jsの`defer`で`setTimeout(func,
0)`ではなく1msが指定されている理由は、古いChromeでUIスレッドがブロックされることがあるからのようです(?)。

<https://github.com/lodash/lodash/pull/1334#issuecomment-120736265>

> We avoid a setTimeout of 0 because I believe old Chrome could end up
> blocking the UI thread with them.

* * *

`setTimeout(func, 0)`について

7.4. Timers  
<http://w3c.github.io/html/webappapis.html#timers>

`timeout`の初期値は0msで省略可能です。

ただし、タイマーの`nesting level`が5より大きく`timeout`が4msより小さい場合、`timeout`は4msに設定されます。

> NOTE:  
>  Timers can be nested; after five such nested timers, however, the interval
> is forced to be at least four milliseconds.

>   8. If nesting level is greater than 5, and timeout is less than 4, then
> increase timeout to 4.
>

* * *

0ms(初期値)の場合、`scheduled to run at the next
opportunity`ですが、いつ実行されるかはタスクに積まれているキューの状態に依存します。

EXAMPLE 11  
<http://w3c.github.io/html/webappapis.html#example-8b53adfc>

[code]

    function rescheduleWork() {
    var handle = setTimeout(rescheduleWork, 0); // preschedule next iteration
    if (doExpensiveWork())
      clearTimeout(handle); // clear the timeout if we don’t need it
    }
    
[/code]

<https://developer.mozilla.org/en-
US/docs/Web/API/WindowTimers/setTimeout#Notes>

> Because even though setTimeout was called with a delay of zero, it's placed
> on a queue and scheduled to run at the next opportunity, not immediately.

<https://developer.mozilla.org/en-
US/docs/Web/JavaScript/EventLoop#Zero_delays>

> Zero delay doesn't actually mean the call back will fire-off after zero
> milliseconds. Calling setTimeout with a delay of 0 (zero) milliseconds
> doesn't execute the callback function after the given interval. The
> execution depends on the number of awaiting tasks in the queue.
[code]

    (function () {
    
      console.log('this is the start');
    
      setTimeout(function cb() {
        console.log('this is a msg from call back');
      });
    
      console.log('this is just a message');
    
      setTimeout(function cb1() {
        console.log('this is a msg from call back1');
      }, 0);
    
      console.log('this is the  end');
    
    })();
[/code]


CC BY-SA 3.0
2016-06-21T07:32:36.943
26914
2016-06-21T07:32:36.943
3068
26909
answer