心に住む推しが定刻に通知を送ってくれる時報Webアプリを作っていたのですが、タイマー機能の実装で行き詰まったのでメモ。

心に住む推しが定刻に通知を送ってくれる時報Webアプリってなんですか?

時報アプリ
こういうことだよ



問題

時報のウィンドウを最小化したり、別タブで作業をしていたり、他のアプリを立ち上げていたりする時、時報が届かないことがあったのです。

なぜ??



原因

時報ウィンドウにフォーカスしていない間、タイマーがうまく機能していませでんした。

というのも、もともとタイマー処理をsetIntervalで書いていたのですが、リソース節約のため、ブラウザ側が裏側でよしなに実行を遅らせたり、停止させたりしていたのですね。

ありがたいけど...この場合ありがたくない。

ずっとカウントし続けて欲しい場合はどうしたらいいんだ?



解決法

Web Workerを使う。


Web Workerってなーに?

教えて、ChatGPT先生!

Web Workerは、ウェブページ上でJavaScriptを実行するための特別な技術の一つです。
通常、ブラウザでJavaScriptが実行されると、その処理は1つのスレッドで行われます。これは単純なページでは問題ありませんが、複雑な処理や大量の計算を行う場合、ページがフリーズしたりレスポンスが悪くなることがあります。

Web Workerは、この問題を解決するために開発されました。Web Workerを使用すると、ブラウザは複数のスレッドでJavaScriptを実行できます。つまり、メインのJavaScriptコードとは別のバックグラウンドスレッドで処理を実行することができます。これにより、メインスレッドがブロックされることなく、ウェブページがスムーズに動作し続けることができます。


ということで、以下のようなことをしたい時に有用な機能です。

・バックグラウンドで重い処理や計算を実行する。

・ウェブページとは別のスレッドでデータを処理する。


今回の実装では、Web Worker君に常に裏側で時間のカウントを取り続ける作業をしてもらうことにした、というわけです。



具体的な実装

コードの一部を切り出してみました。


何をしているか

バックグラウンドでやりたい処理は、別ファイル(workerTimer.js)に切り出して実装しておきます。

現在時刻を一秒ごとに時間をカウントアップしていく実装を書いています。

  postMessage(currentFormattedTime);

という形で、postMessageが結果を返してくれます。


呼び出し元はmain.jsです。

切り出しておいた実装を 

  const worker = new Worker("./workerTimer.js");

のように呼び出します。

  worker.onmessage = (event) => {}

という形で呼び出して、event.dataの中で、送られてきたデータ(この場合、一秒ごとにアップデートされていく時間)を取得できます。



結果

実装しつつこのブログを書いてたら、無事に通知が来ました。

あ゛あ゛あ゛ぁQOL高まる〜〜〜〜っ!!!(クソデカボイス)

時報アプリ