Webアプリケーションでの定期的なデータ通信は、ユーザーがブラウザのタブを非アクティブにした場合に停止してしまうことがあります。特にスマートフォンでは省電力機能やブラウザの最適化によって、バックグラウンド通信が不安定になることがよくあります。この記事では、非アクティブ状態でも安定した通信を行うための考え方と実装方法を具体例とともに解説します。
バックグラウンド通信が止まる原因
ブラウザが非アクティブになると、JavaScriptのsetIntervalやsetTimeoutなどのタイマーが遅延することがあります。また、fetchやXHRなどのHTTP通信も、タブがバックグラウンドになると優先度が下がり、通信が遅れたり中断されることがあります。
スマートフォンのブラウザではさらに省電力モードやOSレベルの制約が加わるため、バックグラウンド通信はより不安定になります。このため、常にリアルタイムで通信を行うような実装は避け、タブの状態に応じた制御が必要です。
Page Visibility APIの活用
非アクティブタブの検知には、JavaScriptの Page Visibility API が便利です。document.visibilityState を使うことで、タブが表示中か非表示中かを判定できます。
例えば、setIntervalで定期的にサーバーにデータを送信する場合、タブが非表示のときは通信を止め、再び表示されたときにまとめて更新する、といった制御が可能です。
document.addEventListener('visibilitychange', () => {
if(document.visibilityState === 'visible'){
startFetching();
} else {
stopFetching();
}
});
Service Workerを使ったバックグラウンド同期
より高度な方法として、Service Worker を利用したバックグラウンド同期(Background Sync)があります。これを使うと、ユーザーがアプリを閉じていても、ネットワーク接続が回復したタイミングでサーバーにデータを送信できます。
例えば、オフラインで入力されたデータをバックグラウンドで送信するケースでは、fetchをService Worker内で扱い、同期完了後に通知を行うことも可能です。[参照]
WebSocketによるリアルタイム通信の工夫
頻繁なデータ更新が必要な場合は、WebSocketを利用すると効率的です。ただし、バックグラウンドでの接続維持はブラウザによって制限されることがあります。そのため、非アクティブ時は接続を一時停止し、アクティブになったら再接続する戦略が現実的です。
再接続時にはサーバー側での状態管理も重要です。例えば、未取得のメッセージをまとめて送信するキューイング機能をサーバーに実装しておくと、通信の中断によるデータ欠損を防げます。
定期通信の代替戦略
どうしても非アクティブでも通信を維持する必要がある場合、サーバー側でプッシュ型の通知を活用する方法があります。Web Push APIやFirebase Cloud Messaging(FCM)を使うことで、クライアントが非アクティブでも通知を受け取り、必要に応じて通信を再開できます。
この方法は、クライアントが常にポーリングする必要がなくなるため、省電力かつ通信効率も高くなります。
まとめ
ブラウザタブが非アクティブになると通信が遅延・停止する問題は、Page Visibility APIで状態を判定したり、Service WorkerやWeb Pushを活用することで解決できます。単純なsetIntervalによるポーリングだけでは安定性に欠けるため、状況に応じて非アクティブ時の通信停止やバックグラウンド同期を組み合わせることが推奨されます。
実際の実装では、アプリの用途や更新頻度に応じて、ポーリング、WebSocket、Service Worker、Push通知などを柔軟に組み合わせることが重要です。


コメント