LoginSignup
115
58

More than 5 years have passed since last update.

setTimeout()の0秒は4ミリ秒

Last updated at Posted at 2019-01-23

window.setTimeout()がコールバックのネストにより連続的に呼ばれたとき、4ミリ秒の遅延が発生します。
たとえば以下のコードでは、countを1000にするのに4秒以上かかります。

let start = new Date().getTime();
let count = 0;
let next = () => {
  count++;
  if (count === 1000) {
    console.log((new Date().getTime() - start) / 1000);
  } else {
    window.setTimeout(next, 0);
  }
};
let id = window.setTimeout(next, 0);

MDNのページで言及されていました。「4ミリ秒」というのはHTML5で標準化された仕様です。

解決策も書かれており、window.postMessage()を使えばいいようです。
以下のコードを実行すると、countを1000にするのに0.070秒で済みます。

let start = new Date().getTime();
let count = 0;
let next = (e) => {
  if (e.source !== window) return;
  count++;
  if (count === 1000) {
    console.log((new Date().getTime() - start) / 1000);
  } else {
    window.postMessage("");
  }
};
window.addEventListener("message", next, false);
window.postMessage("");

何らかの重い処理をしている間もユーザーの入力を受け付けたい、けど重い処理もできるだけ早く終わらせたい場合に、window.postMessage()の使用を検討するといいかもしれません。

補足

if (e.source !== window) return;は、メッセージの送信者が何者かを判定しています。この行を外してしまうと、クロスサイトスクリプティング攻撃を受けてしまう可能性が出てくるとのこと。MDNのページに明記されています。

115
58
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
115
58