前回の[Service WorkerでPush通知を試す]では1つの端末に対してプッシュ通知を行うことができたが、全体やグループに通知するための課題や問題点が残されていた。いくつかのサイトを参考にグループごとへの通知が可能になったのでそれをまとめる。
## 通知の登録を1度限りにする
Service Workerでエンドポイントを登録するスクリプトを、トップサイトのドキュメントをGETする度に実行してしまっていたため、その度にMySQLへ登録してしまうということが課題だった。サイトを訪れただけで通知の許可を求められることに煩わしさを感じる人も多いため、ボタンのクリックでダイアログを表示する任意式に変更した。
Service Workerを登録するスクリプトにサブスクリプションの可否を判断するコードを追記する。
```javascript
registration.pushManager.getSubscription().then(subscription => {
if (!subscription) {
// 通知の確認がまだされていない時の処理
} else {
// すでにサブスクリプションが登録されているときの処理
}
});
```
onclickをトリガーにスクリプトを実行するbuttonタグをドキュメント内に追記。サブスクリプションが発行されていなければボタンを表示するように処理を!subscription内に書いておく。javascriptとPHPでやりとりをするためにcookieで状態を保存したが反映が遅いので要修正。
```markup
```
enablePushNotification()関数でダイアログを表示し、MySQLに登録するスクリプトを実行。エンドポイントだけで通知が可能であることがわかったのでエンドポイントだけを登録する。
```javascript
const enablePushNotification = () => {
navigator.serviceWorker.ready.then(registration => {
return registration.pushManager.subscribe({ userVisibleOnly: true });
}).then(subscription => {
registerInMySQL(subscription.endpoint);
}).catch(console.error.bind(console));
}
```
registerInMySQLで同ディレクトリ内のpost.phpにエンドポイントをPOST。データベースの内容は省略(いずれ書くかも)
```javascript
const registerInMySQL = (endpoint) => {
fetch('./post.php', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `endpoint=${endpoint}`,
}).then(response => {
alert('登録完了');
}).catch(error => {
console.error(error);
alert('登録失敗');
});
}
```
## 参考
[PWAの基礎知識(その8)「Push API/Chrome編」](https://blog.htmlhifive.com/2018/07/20/pwa-push-api-chrome/)
[Service WorkerでPush通知を試す]: https://hi97.hamazo.tv/e8238205.html