Javascript 将消息从注册服务工作者发送到客户端页面
当registration onupdatefound函数被触发时,我试图向app.js发送一个变量(布尔值),这样每当收到新的更新时,app.js就会知道,然后我就可以显示一个带有刷新按钮的弹出窗口 在我实现的大部分部分中,我只是对app.js如何在“message”addEventListener上接收数据感到困惑,因为我无法从中接收任何数据 先谢谢你 registerServiceWorker.js service-worker.js app.jsJavascript 将消息从注册服务工作者发送到客户端页面,javascript,reactjs,web,service-worker,Javascript,Reactjs,Web,Service Worker,当registration onupdatefound函数被触发时,我试图向app.js发送一个变量(布尔值),这样每当收到新的更新时,app.js就会知道,然后我就可以显示一个带有刷新按钮的弹出窗口 在我实现的大部分部分中,我只是对app.js如何在“message”addEventListener上接收数据感到困惑,因为我无法从中接收任何数据 先谢谢你 registerServiceWorker.js service-worker.js app.js 在CRA v3中,onSuccess和o
在CRA v3中,
onSuccess
和onUpdate
回调可以作为选项
传递给服务工作者。注册
通常,这些回调会更新应用程序存储,这反过来会影响UI组件
对于最低限度的CRA v3演示:
//App.js
从“React”导入React;
导入“/App.css”;
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
this.state={message:'Hello World'};
//设置回调以获取
//服务人员安装状态
//
this.props.listen(状态=>{
this.setState({message:status});
});
}
render(){
返回(
{this.state.message}
);
}
}
导出默认应用程序;
//index.js
从“React”导入React;
从“react dom”导入react dom;
导入“./index.css”;
从“./App”导入应用程序;
将*作为serviceWorker从“/serviceWorker”导入;
const{listen,onUpdate,onSuccess}=setupStatusTransfer();
ReactDOM.render(
您是否试图通知所有当前打开的选项卡(窗口)由服务人员提供服务的消息?这可能有点问题,因为您依赖于旧服务人员正确处理新注册发布的消息-最终您不知道当前在职服务人员有多过时
也就是说,要在React组件中处理postMessages
,您应该使用componentDidMount
和componentWillUnmount
生命周期方法(或useffect
hook)
以下简化示例使用带有workerize loader
的专用Web Worker,但原理保持不变:
//App.js
从“React”导入React;
导入“/App.css”;
类应用程序扩展了React.Component{
建造师(道具){
超级(道具);
this.state={count:'?'};
const nf=新的Intl.NumberFormat(navigator.language,{minimumIntegerDigits:6});
this.receive=事件=>{
const{data:count}=事件;
如果(计数类型=='number'){
this.setState({count:nf.format(count)});
}
};
}
componentDidMount(){
this.props.worker.addEventListener('message',this.receive);
}
组件将卸载(){
this.props.worker.removeEventListener('message',this.receive);
}
render(){
返回(
{this.state.count}
);
}
}
导出默认应用程序;
//带挂钩的App.js
从“React”导入React,{useState,useffect};
导入“/App.css”;
函数应用程序({worker}){
const[count,setCount]=useState(“?”);
常量订阅=()=>{
返回listenForUpdates(worker,setCount);
}
使用效果(订阅[工作人员]);
返回(
{count}
);
}
函数listenForUpdates(worker,setCount){
常数nf=新的整数格式(
navigator.language,
{最小整数位数:6}
);
const receive=({data})=>{
如果(数据类型=='number'){
setCount(nf.格式(数据));
}
};
常量清理=()=>{
worker.removeEventListener('message',receive)
};
worker.addEventListener(“消息”,接收);
回流清理;
}
导出默认应用程序;
//index.js
从“React”导入React;
从“react dom”导入react dom;
导入“./index.css”;
从“./App”导入应用程序;
//eslint禁用下一行导入/无网页包加载程序语法
从“workerize loader.”导入工作者!/worker';
让实例=worker();
实例.启动(1000);
ReactDOM.render(
-在navigator.serviceWorker.controller
上可以找到属性(在那里可以找到属性)
更新:使用Create React,应用程序4已成为选择性加入,即不再包含在默认CRA模板中
ServiceWorker包含在cra模板pwa
()中,该模板本身通过库使用ServiceWorker
npx创建反应应用程序我的应用程序--模板cra模板pwa
ServiceWorker注册逻辑已被分离到serviceWorkerRegistration.js
——与service worker.js
分开。此外,ServiceWorker仅为正在服务的生产版本注册。要生成:
纱线运行构建
然后服务,比如:
http服务器-c-1./build
最小cra模板pwa
v4演示:
//文件:registrationStatus.js
从“react”导入{useState,useEffect};
让电流='不变';
const subscriptions=new Set();
函数订阅(setStatus){
订阅。添加(setStatus);
return()=>{
订阅。删除(setStatus);
};
}
功能分派(状态){
当前=状态;
forEach((setStatus)=>setStatus(status));
}
函数useStatus(){
常量[状态,设置状态]=使用状态(当前);
useffect(()=>subscribe(setStatus),[]);
返回状态;
}
//已更新但正在等待过时选项卡关闭
函数onUpdate(_注册){
派遣(“更新”);
}
//更新并运行
函数onSuccess(_注册){
派遣(“成功”);
}
导出{useStatus,onUpdate,onSuccess};
//文件:App.js
从“/registrationStatus”导入{useStatus};
函数App(){
const status=useStatus();
return注册状态:{status}
;
}
导出默认应用程序;
//文件:ind
registration.onupdatefound = () => {
console.log('sw onupdatefound');
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
console.log('sw onstatechange',navigator.serviceWorker);
if (installingWorker.state === 'installed') {
console.log('sw onstatechange//',navigator.serviceWorker);
if (navigator.serviceWorker.controller) {
// available; please refresh." message in your web app.
console.log('New content is available; please refresh...');
navigator.serviceWorker.controller.postMessage({
data: {
toUpdate: true,
},
});
} else {
console.log('Content is cached for offline use.');
}
}
};
};
self.addEventListener('fetch', (event) => {
console.log('in fetch of s-w');
self.clients.matchAll().then(all => all.map(client => client.postMessage(event)));
});
self.addEventListener('message', (event) => {
console.log('event msg from s-w', event.data);
if (event.data.toUpdate) {
console.log('updating');
self.skipWaiting();
}
// Select who we want to respond to
self.clients.matchAll().then(all => all.map(client => client.postMessage(event.data)));
self.clients
.matchAll({
includeUncontrolled: true,
type: 'window',
})
.then((clients) => {
clients.postMessage(event.data);
if (clients && clients.length) {
// Send a response - the clients
// array is ordered by last focused
clients[0].postMessage(event.data);
}
});
});
navigator.serviceWorker.onmessage = (event) => {
console.log('event in app.js nav on msg', event);
if (event.data.toUpdate) {
alert('Please refresh your page to upadate service worker');
}
};
window.addEventListener('message', (event) => { console.log('new event ====>', event); });