worker服务器推送消息,浏览器中serviceWorker用法
朋也的博客 » 首页 » 文章
浏览器中serviceWorker用法
作者:朋也
日期:2019-05-27
类别:javascript学习笔记
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
上一篇博客介绍了PWA的用法,最后留了个serviceWorker用法没有说,这一篇来介绍一下
先上图
先说一下流程:生成公/私钥 -> 浏览器中使用公钥注册服务 -> 服务端使用私钥推送 -> 浏览器中接收推送展示
流程图网上非常多,我这就不截图展示了
生成密钥
我这使用nodejs语言来实现,其它语言版本也有,不过没有nodejs用起来方便
创建一个文件夹 push-demo 在文件夹内安装 web-push 包依赖,然后创建一个 test.js 加上下面代码,运行即可
const webpush = require("web-push");
// 生成公钥私钥
const vapidKeys = webpush.generateVAPIDKeys(); // 1.生成公私钥
console.log(vapidKeys);
结果如下
{ publicKey:
'BK_LXU7DEQ5rAfk8kCNsa-5E9ntYKUoBemBjO-ZaEjpK3PFKCzpUAfYqlk1p2wmbsNBnYSRALpyddMDhHuspPag',
privateKey: 'bC665pacSeHbHv9iY4H0106oUTJWTTyUAsbwEnXX1Mg' }
浏览器注册服务
有了公钥,就可以在浏览器里通过代码注册服务了,代码如下,注释都写好了,看一下就明白了
function urlB64ToUint8Array(base64String) {
const padding = "=".repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, "+")
.replace(/_/g, "/");
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
const publicKey =
"BK_LXU7DEQ5rAfk8kCNsa-5E9ntYKUoBemBjO-ZaEjpK3PFKCzpUAfYqlk1p2wmbsNBnYSRALpyddMDhHuspPag";
// 判断浏览器是否支持serviceWorker,支持的话,注册服务
if ("serviceWorker" in navigator) {
send().catch(err => console.error(err));
}
async function send() {
console.log("Registering service worker...");
// 这里要注册serviceWorker,要提前写一个js,(注意路径),后面接收推送就是在这个js里通过代码实现的
// 这个js创建好就可以了,暂时不需要写东西
navigator.serviceWorker.register("/sw.js").then(register => {
// 判断浏览器是否有推送服务支持
if (window.PushManager) {
register.pushManager.getSubscription().then(subscription => {
// 如果用户没有订阅
if (!subscription) {
// 调用浏览器api,提示用户是否开启网站推送服务
register.pushManager
.subscribe({
userVisibleOnly: true,
applicationServerKey: urlB64ToUint8Array(publicKey) // 密钥还要将其转换一下,否则会报错,转换的代码是固定的,我这里用的就是网上找的
})
.then(subscription => {
// 用户同意接收网站的消息推送,则发送一个请求跟服务端创建连接
fetch("/subscription", {
method: "post",
body: JSON.stringify(subscription),
headers: {
"content-type": "application/json"
}
});
})
.catch(err => console.log("用户没有同意开启通知...", err));
} else {
fetch("/subscription", {
method: "post",
body: JSON.stringify(subscription),
headers: {
"content-type": "application/json"
}
});
console.log("You have subscribed our notification");
}
});
}
});
}
服务端响应
如果浏览器端用户同意了接收推送服务的功能,然后发起了一个跟服务器保持连接的请求,服务端要做相应的处理,将传过来的数据持久化,后面发送推送要用到
浏览器如果同意,然后发送一个连接的请求,传给服务端的数据长这个样
如果是Chrome浏览器,则长下面这个样
{
endpoint:
"https://fcm.googleapis.com/fcm/send/cZdEewi209A:APA91bGo9U4c9ycxJkeIGRlpR-sl0eKafNvtLSVJd_kW--IDe7LY-N-YCsVqC4oLBE1DEKD6JHvVMuNxFq3ANgw9orH1Eo3-JLTRodNyYYn-5Xzz0IM80cfBFuDXWby8gdVudLMb96_j",
expirationTime: null,
keys: {
p256dh:
"BGMG0WgSZueddroRLDxxwFezTTtgby1tT7mJnTv-BDynkTAo_hjroyTfuWa6zbpr6R9xkqPt-rN3mvZnIPwMwpk",
auth: "wWYPAHPDCnAE8y6oTPWj-w"
}
}
如果是firefox浏览器则长下面这个样
{
endpoint:
"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABc57EZB3ZRqMvOUXfFkXY_CXowfxF45Kr76pyMPTeA6vCgEBWieKYC2dwoqsXRkibhavFh9xJwK1llZwnDfCzGIEiMJxFMgQcHp69meonmL1Wlu8ij_MTwlsf54Y-die8D9wIpMjkjnl9wiWVezcapOFBSRzbBA_nfwUtHpkTBG1w6iXs",
keys: {
auth: "4kTmhdWGaWLoZReISaXj1w",
p256dh:
"BKadOZ_MoS_GTdtYMhuCdWoO5S_gcerg71dD-Pk0YpHXpzyD5JKLS9FsWPhPXWgB1Ca0H74cRsUlufruMNzc5Mo"
}
}
我这里是将其入库,有推送的时候,直接查询然后调用推送方法直接推送消息
exports.subscription = async (ctx) => {
// 获取user-agent用于判断浏览器
const user_agent = ctx.headers['user-agent'];
// 获取订阅的信息,入库时将其转成字符串保存即可
const subscription = ctx.request.body;
const user = ctx.session.user;
let chrome_subscription, firefox_subscription;
if (user_agent.indexOf('Chrome') > -1) chrome_subscription = subscription;
if (user_agent.indexOf('Firefox') > -1) firefox_subscription = subscription;
await user_service.update_user_subscription_by_id(
user.id,
JSON.stringify(chrome_subscription),
JSON.stringify(firefox_subscription)
);
ctx.response.status = 201;
ctx.body = {};
};
发送推送
众所周知,国内google的服务是请求不通的,所以我这用firefox的推送服务来演示
首先在上面注册时写的sw.js文件里实现接收推送消息的代码
// 接收推送消息事件
self.addEventListener("push", function (event) {
console.log("[Service Worker] Push Received.");
console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);
let notificationData = event.data.json();
// 弹消息框
event.waitUntil(
self.registration.showNotification(notificationData.title, notificationData)
);
});
// 通知被点击了的事件,比如打开一个链接之类的
self.addEventListener("notificationclick", function (event) {
console.log("[Service Worker] Notification click Received.");
let notification = event.notification;
notification.close();
// event.waitUntil(self.clients.openWindow(notification.action));
// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
self.clients
.matchAll({
type: "window"
})
.then(function (clientList) {
for (let i = 0; i < clientList.length; i++) {
let client = clientList[i];
if (client.notification.url === "/" && "focus" in client) {
// return client.focus();
return self.clients.openWindow(client.notification.url);
}
}
if (self.clients.openWindow && notification.data.url) {
return self.clients.openWindow(notification.data.url);
}
})
);
});
服务端推送消息
const webpush = require("web-push");
let publicKey = 'BK_LXU7DEQ5rAfk8kCNsa-5E9ntYKUoBemBjO-ZaEjpK3PFKCzpUAfYqlk1p2wmbsNBnYSRALpyddMDhHuspPag';
let privateKey = 'bC665pacSeHbHv9iY4H0106oUTJWTTyUAsbwEnXX1Mg';
webpush.setVapidDetails(
"mailto:py2qiuse@gmail.com",
publicKey,
privateKey
);
const firefoxSubscription = {
endpoint:
'https://updates.push.services.mozilla.com/wpush/v2/gAAAAABc61hnBVOJZIOLZgSN7x8Pom_AKoVvE4yAaCi0wnWaXv05FAVGx2tlMSPAkKCaj_DnYDzmyWRJGwofpuYuXDiDPX2RSNUmTiXfgTP55t9c82UzFdeZvvkvqr2vdD-H1QIfIGd3LJzh58Pd6SRey2su91F160ilKsz_3AOzGAEv_FloXeY',
keys:
{
auth: '9-beSGAEs_f5JM4Dkit-vw',
p256dh:
'BEfxlwj1XLIEBWFa-Bc7TS2aMQLcJK9H0mSbl5OSkN1vFPAEJJZRfeHDpz09JDUx6QhA9YG7Wjm7d7dXq10ixQ4'
}
};
// push的数据
const payload = {
title: "测试推送",
body: "推送内容,一串链接,点击打开",
icon: "https://yiiu.co/favicon.ico",
data: {url: "https://tomoya92.github.io/pybbs/", text: 'hello world'},
};
// 发送通知
webpush.sendNotification(firefoxSubscription, JSON.stringify(payload));
运行代码,firefox上就可以收到一条推送消息了
补充:payload的数据格式这见个是固定的,如果你想自定义一些数据,可以写在data对象里,在sw.js里点击事件里可以获取到,然后做相应的处理
sw.js里的点击通知事件回调参数里有一个 notification 对象,这个对象就是在 接收通知事件里打开通知的方法中传入的第二个参数对象,如果传的是服务端推送的消息对象,那也就是payload对象,可以直接拿data中的url通过调用 openWindow()方法打开这个链接
不得不说,还是chrome方便,可以直接对sw.js里的代码进行调试,在firefox上开发调试真心麻烦 。。。
worker服务器推送消息,浏览器中serviceWorker用法相关推荐
- worker服务器推送消息,关于Worker如何向指定Client推送消息
use Workerman\Worker; require_once './Workerman/Autoloader.php'; // 初始化一个worker容器,监听1234端口 $worker = ...
- 服务器推送消息方法总结及实现(java)
服务器推送消息方法总结及实现(java) 最近在进行web开发时,有用到服务端推送消息这个功能,相信大家在平常开发时,也经常会有这种需求.本文对常用的几种服务器推送消息方法进行整理和总结,并实现使用流 ...
- html5服务器推送消息的各种解决办法,WEB服务器推送消息的各种解决办法
前言:在各种BS架构的应用程序中,往往都希望服务端能够主动地向客户端推送各种消息,以达到类似于邮件.消息.待办事项等通知.而BS架构本身存在的问题就是,服务器一直采用的是一问一答的机制.这就意味着如果 ...
- HTTP Websocket 服务器推送消息
文章目录 HTTP HTTP请求过程 1. 无状态 2. 基于TCP协议 心跳包 3. 长.短连接 4. 单向请求 传统服务器推送技术 短轮询 polling 同源限制 跨域资源共享 长轮询 long ...
- asp服务器推送消息,asp.net实时向客户端推送消息(SignalRWeb)
[实例简介]ASP.net中服务器端向客户端推送消息,多用于在线聊天 [实例截图] [核心代码] using System; using System.Collections.Generic; usi ...
- java服务器推送消息技术
其实有很多种方式实现服务器推送,它们各有各的优缺点: 1.传统轮询:此方法是利用 HTML 里面 meta 标签的刷新功能,在一定时间间隔后进行页面的转载,以此循环往复.它的最大缺点就是页面刷性给人带 ...
- netty多台服务器 推送消息,基于Netty的消息推送服务器集群设计与实现
徐龙光 何顶新 摘 要:消息推送是当前移动应用中十分必要的一项技术,服务者需要使用消息推送以保持用户活跃度,提高应用存留率.为了满足消息推送的需求和增强推送系统的性能,采用Netty网络编程框架并搭建 ...
- Android Notification实现推送消息过程中接受到消息端有声音及震动及亮屏提示
在Android Notification状态栏通知一文中,简单实现了消息的推送效果,这里就接着上文说一下,当用户接受到消息时的提示效果 // 5-加入震动及声音及亮屏 notification.de ...
- 手机 服务器 推送消息推送消息,推送信息到手机的pushover使用方法及sample code
今天给大家介绍一个好东西,用了两年多了,一直没时间给大家推荐.pushover,移动端的信息推送服务API,包括使用.设置以及API实现. 用途 在关键节点放上推送(比如用户注册.举报.评论,系统检测 ...
最新文章
- Ubuntu安装Beyond-Compare 4
- (用微信扫的静态链接二维码)微信native支付模式官方提供的demo文件中的几个bug修正...
- (2006, 'MySQL server has gone away') 错误解决 - dba007的空间 - 51CTO技术博客
- beta book读书俱乐部的构思
- Memcached原理深度分析详解
- 笔记6 | 从源码理解分析mScrollX和mScrollY,scrollTo()和scrollBy(),smoothScrollTo和smoothScrollBy...
- [蓝桥杯]最大连续子序列和
- 【亲测】二极管电压测试“跳坑”注意事项——硬件的板载测试验证
- 细数Android开发者的艰辛历程,全网最新
- python快速排序代码_Python实现快速排序算法
- 民意调查Django实现(一)
- Java 核心五个类(File、Outputstream、Inputstream、Reader、Writer)一个接口(Serializable)...
- 中国联通与小米深度联动 联合推出Wi-Fi 6路由器AX3600
- free释放链表节点崩溃_【链表6】lt;最新gt;初识链表(link list)
- 昔日的 HTC 与三星,今日的苹果:寒冬过后手机厂商才会明白的潜规则
- VS2008下改变项目的默认属性
- 物联网可视化平台-场景编辑器-轻松实现三维地图搭建
- CnPack应用总结
- qq游戏大厅+android,手机QQ游戏大厅Android客户端体验
- Java初学笔记30-【MiniQQ聊天部分代码】