深入浅出现代 JavaScript—通知(1)

270 阅读2分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

介绍通知 API 前端对用户的通知一般局限于页面之内,比如 alert,confirm。或者 javascript 控制一个弹窗提醒用户。有些场景需要在页面之外通知用户,也就是当用户页签不在本页面,或者浏览器已经被收起来的情况。

<script>
    // default granted denied
    console.log(Notification.permission)
</script>

首先判断一下是否获取接收通知的权限,上面代码用于检查当前页面是否有接收消息。对于Notification.permission 有 3 种取值 ,

  • defulat
  • granted
  • denied

当输出为denied 表示不允许接收该网页的通知,所以需要更改设定

  • 在浏览器右上角更多菜单中选择"设置"
  • 在右侧菜单中选择"隐私设置与安全性"
  • 然后在左侧页面中选择"网站设置"
  • 在"网站设置"页面中,下拉至"通知",选择"通知"
  • 在"通知"页面中,将要接收通知页面添加到"允许发送通知"列表即可
<script>
    // default granted denied
    // console.log(Notification.permission)
    if (Notification.permission === "granted") {
        console.log("we have permission")
    } else {
        Notification.requestPermission().then(permission => {
            console.log(permission)
        })
    }
</script>
function showNotification() {
    const notification = new Notification("message from my site", {
        body: "modern JS is coming soon."
    })
}

屏幕快照 2021-11-04 下午1.09.00.png

接下来我们来实现比较完整的例子,首先通过我们先实现客户端代码,

addEventListener('load', async () => {
    let sw = await navigator.serviceWorker.register('./sw.js');
    console.log(sw);
});

async function subscribe(){
    let sw = await navigator.serviceWorker.ready;
    let push = await sw.pushManager.subscribe({
        userVisibleOnly:true,
        applicationServerKey:'TODO'
    })
}
  • 监听加载页面事件load 回调函数为异步回调函数中注册一个 serviceWork
  • 那么什么又是 serviceWork, serviceWork 是web 应用和远端服务中间的可编程的代理,有了 serviceWork 我们就可以对网络请求进行更多的控制
  • 当 serviceWork 准备好了,就可以订阅服务端消息,这里需要一个应用 applicationServerKey 不过接下来我们需要在服务端生成一下,

例如,serviceWork 可以控制对网站 HTML 请求的缓存行为,并将其与对网站图片的请求区别对待。服务工作者还使你能够处理推送信息。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button onclick="subscribe()">Subscribe</button>
    <script>
        addEventListener('load', async () => {
            let sw = await navigator.serviceWorker.register('./sw.js');
            console.log(sw);
        });

        async function subscribe(){
            let sw = await navigator.serviceWorker.ready;
            let push = await sw.pushManager.subscribe({
                userVisibleOnly:true,
                applicationServerKey:'TODO'
            })
        }
    </script>
</body>

</html>

服务器端

在服务端需要安装 web-push 库,然后将其引用。首先我们调用 generateVAPIDKeys API 来生成 API IDKey

var push = require('web-push');
// console.log(push)
var vapiKeys = push.generateVAPIDKeys()

console.log(vapiKeys)

输出的publicKeyprivateKey 如下,现在我们就可以

{ publicKey: 'BC0IMqzFaJ3hFWPfNC0HrEQmkDTkUO6vxyboEoedg_NRINZJ8nneeg-RWANIgRTM5IHGkmi_lGLmrOz8uw5AFPE',
  privateKey: 'ZtomiE0Kv21A2TIJNAvrlufDKiks1241Ezv5iOcJaVU' }