Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/434.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将消息从注册服务工作者发送到客户端页面_Javascript_Reactjs_Web_Service Worker - Fatal编程技术网

Javascript 将消息从注册服务工作者发送到客户端页面

Javascript 将消息从注册服务工作者发送到客户端页面,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

当registration onupdatefound函数被触发时,我试图向app.js发送一个变量(布尔值),这样每当收到新的更新时,app.js就会知道,然后我就可以显示一个带有刷新按钮的弹出窗口

在我实现的大部分部分中,我只是对app.js如何在“message”addEventListener上接收数据感到困惑,因为我无法从中接收任何数据

先谢谢你

registerServiceWorker.js

service-worker.js

app.js


在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); });