@amiii has joined

@amiii

Created at 2022-09-22T02:52:55.144781Z / Updated at 2022-09-22T02:52:55.144822Z

【JavaScript】settimeout()が動作しない場合の対処

ChromeブラウザなどのJavaScriptでは、settimeout()は対象のウィンドウがアクティブ/フォーカスされている状態でないと動作が不安定になることがあります。

これはChromeなどの多くのブラウザがウィンドウがアクティブでない時にCPUの最適化の一つとして自動で動作する挙動です。

javascript - window.setTimeout behaviour when window not in focus - Stack Overflow modern browsers (especially on mobile devices) suspend execution of scripts in tabs that are out of focus to save CPU cycles

以下のスタックオーバーフローのページを参考にすると、多くの投稿が以下のようなsettimeoutを利用したsleep関数の実装をしています。

const sleep = m => new Promise(r => setTimeout(r, m));

これは以下のようにDate()を利用して相対的な待機でなく絶対的な待機とすることができます。

const sleep2 = (seconds) => {
    const waitUntil = new Date().getTime() + seconds * 1000
    while(new Date().getTime() < waitUntil) {
        // do nothing
    }
}

しかし、上記のwhile()を利用した方法は実行を停止/ハングさせてしまうため、settimeout()の方法とはまた違った問題/エラーに遭遇することになる場合があります。

その場合、以下の方法がよりオールラウンドに活用できます。 最適化面、CPUには少し優しくありませんが、より確実に実行してくれます。


const sleep = m => new Promise(r => setTimeout(r, m));

const sleep2 = (mseconds) => new Promise(async r => {
    const waitUntil = new Date().getTime() + mseconds
    for (let i = 0; i < Infinity; i++) {
        if (new Date().getTime() < waitUntil) {
            await sleep(100);
        } else {
            break;
        }
    }
    r();
});

これを以下のように利用します。

(async () => {
    console.log("y")
    await sleep2(1000) // 1秒待機
    console.log("yy")
})();
Comments(2)
Comment as Guest