setTimeoutで数秒ではなく数十分など長めに設定した場合に、上手く挙動しなかったことがありました。
##setTimeout
指定時間後にJavaScript関数を実行するsetTimeout。
ページを開いたまま20分経過したら自動で指定ページに遷移させようとしました。
setTimeout(function(){
window.location.href = 'https://xxx.ne.jp/';
}, 20 * 60 * 1000);
普通思い浮かぶであろうこのコードでなんの問題もなく処理が動きそうです。(と思ってました...)
ただ、このsetTimeoutはAndroidやiOSといったスマホ・タブレット端末のWebブラウザでは注意する必要があります。
スマホ・タブレット端末では、アプリがバックグランドに入るスリープの概念があり、この状態ではsetTimeoutの呼び出し(JavaScriptの実行そのもの)も保留されてしまいます。
スリープ中に止まったタイマーが完了するのは、1分後かもしれないし10分後、1時間後かもしれません...。
##経過時間をチェックしてスリープ対策
スマホユーザーが多いサービスがゆえにスリープ対策をどうしてもしなければならなかったので、setIntervalで「ページを開いてから20分経過したか」を定期的にチェックし続ける処理を入れることにしました。
- setTimeout関数 ・・・ 指定した時間経過後に処理を実行する
- setInterval関数 ・・・ 指定した時間ごとに処理を実行する
- clearTimeout関数 ・・・ setTimeoutで設定したタイマーを取り消す
- clearInterval関数 ・・・ setIntervalで設定したタイマーを取り消す
※時間の指定単位は「ミリ秒」
// 20分後指定URLにリダイレクト
const setTime = Date.now() + (20 * 60 * 1000);
const timer_Id = setInterval(() => {
if (Date.now() > setTime) {
clearInterval(timer_Id);
window.location.href = 'https://xxx.ne.jp/';
}
}, 500);
この処理だと、途中でスリープしていた場合でも
- ページを開いてから20分後に処理が走る
- スリープ中に20分を過ぎていたら復帰した瞬間に実行される
今回は1秒だと微妙だったので0.5秒(500ミリ秒)でIntervalを指定しました。
##最後に
「Webブラウザがバックグラウンドに回ってスリープ状態になり処理が止まる」という事象はPCでは起こりにくいので、AndroidやiOSで挙動が変わることがあるという点は注意すべきところですね。