我试图在触发注册onupdatefound函数时将变量(布尔值)发送到app.js,所以每当收到新更新时,app.js就会知道,然后我可以显示带有刷新按钮的弹出窗口
我已经实现了大部分,因为我的app.js将如何从“ message” addEventListener接收数据而感到困惑,因为我无法从其中接收任何数据。
先谢谢您
registerServiceWorker.js
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);
}
});
});
service-worker.js
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); });
app.js
{{1}}
答案 0 :(得分:1)
在CRA v3中,onSuccess
和onUpdate
回调可以作为options
传递到serviceWorker.register
。
通常,这些回调会更新应用程序存储,从而影响UI组件。
对于最小的CRA v3演示:
// App.js
import React from 'react';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {message: 'Hello World'};
// setup callback to get
// service worker installation status
//
this.props.listen(status => {
this.setState({message: status});
});
}
render() {
return (
<p className="App">{this.state.message}</p>
);
}
}
export default App;
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
const {listen, onUpdate, onSuccess} = setupStatusTransfer();
ReactDOM.render(
<React.StrictMode>
<App listen={ listen } />
</React.StrictMode>,
document.getElementById('root')
);
serviceWorker.register({
onUpdate,
onSuccess
});
function setupStatusTransfer() {
let cb;
let status;
const send = s => {
status = s;
if(cb && status) cb(status);
}
const listen = callback => {
cb = callback;
send(status);
};
return {
listen,
onUpdate: makeSendStatus(send, 'update'),
onSuccess: makeSendStatus(send, 'success')
};
}
function makeSendStatus(send, status) {
return _registration => {
send(status);
};
}
另请参阅:Let Users Know When You Have Updated Your Service Workers in Create React App。
您是否要通知服务人员正在服务的所有当前打开的选项卡(窗口)?由于您依靠旧服务人员来正确处理新注册发布到其上的消息,所以这可能会有些问题-最终您不知道已过期当前活跃的服务工作者。
也就是说,要在React组件中处理postMessages
,您应该使用componentDidMount
和componentWillUnmount
生命周期方法(或useEffect
挂钩)。
下面的简化示例将专用的Web Worker与workerize-loader
一起使用,但是原理保持不变:
// App.js
import React from 'react';
import './App.css';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {count: '?'};
const nf = new Intl.NumberFormat(navigator.language, {minimumIntegerDigits: 6});
this.receive = event => {
const { data: count } = event;
if (typeof count === 'number') {
this.setState({count: nf.format(count)});
}
};
}
componentDidMount() {
this.props.worker.addEventListener('message', this.receive);
}
componentWillUnmount() {
this.props.worker.removeEventListener('message', this.receive);
}
render() {
return (
<p className="App">{this.state.count}</p>
);
}
}
export default App;
// App.js with hooks
import React, { useState, useEffect } from 'react';
import './App.css';
function App({ worker }) {
const [count, setCount] = useState('?');
const subscribe = () => {
return listenForUpdates(worker, setCount);
}
useEffect(subscribe, [worker]);
return (
<p className="App">{ count }</p>
);
}
function listenForUpdates(worker, setCount) {
const nf = new Intl.NumberFormat(
navigator.language,
{minimumIntegerDigits: 6}
);
const receive = ({ data }) => {
if (typeof data === 'number') {
setCount(nf.format(data));
}
};
const cleanup = () => {
worker.removeEventListener('message', receive)
};
worker.addEventListener('message', receive);
return cleanup;
}
export default App;
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
// eslint-disable-next-line import/no-webpack-loader-syntax
import worker from 'workerize-loader!./worker';
let instance = worker();
instance.start(1000);
ReactDOM.render(
<React.StrictMode>
<App worker={ instance } />
</React.StrictMode>,
document.getElementById('root')
);
// worker.js for https://github.com/developit/workerize-loader
//
export function start(delay) {
let count = 0;
const sendAndUpdate = () => {
postMessage(count);
++count;
};
setInterval(sendAndUpdate, delay);
}
addEventListener
和removeEventListener
应该可以在ServiceWorker
上获得的navigator.serviceWorker.controller
界面上使用。
(您的app.js
示例尝试navigator.serviceWorker.onmessage
-但navigator.serviceWorker
是ServiceWorkerContainer
-在navigator.serviceWorker.controller
上找到ServiceWorker
-可以找到onmessage
属性。