「バックグラウンドのタブって、JSの処理どこまで制限されるんだろう」というのは、SPLIT TIMER作ってるとき避けて通れなかったテーマです。これまでの記事でも何度か触れてる話ですが、今回は実際に調べた内容をもう少しちゃんとまとめておきます。
setIntervalは裏切る
多くのブラウザは、非表示タブのsetIntervalやsetTimeoutの実行間隔を、バッテリーのために意図的に間引きます。1秒ごとに設定してるつもりでも、裏に回すと数秒〜下手すれば数十秒に1回しか動かないことがある。
これを知らずに素朴な実装をすると、「なんで裏に回すとズレるの」で数時間潰すことになります。
自分がまさにそれでした。
対処は「差分から逆算」
対処法としては、「一定間隔で数える」んじゃなくて「開始時刻を記録しておいて、都度、今の時刻との差分から残り時間を計算し直す」方式にするのが定石です。これなら間引きが起きても、タブが表に戻った瞬間に正しい値へちゃんと復帰します。
あとはdocument.visibilityStateでタブが表示中か非表示かを判定できるので、非表示になったタイミングを検知して、戻ったときに再計算する、みたいな合わせ技も使えます。
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
recalcRemainingTime(); // 表に戻った瞬間に再計算
}
});
ブラウザの省電力機能と真正面から戦っても勝ち目はありません。
「そういうものだ」と割り切って、その前提で設計を組み立てるのが結局一番早い、というのがこのテーマを何度も扱ってきた自分の結論です。
