我想对从服务器收到的推送执行操作。我有一个自定义服务工作者,它具有用于推送的事件侦听器。现在我想在收到服务器的推送时调度 redux 操作。我的自定义服务人员目前位于公共文件夹中。我无法导入此文件中的商店。任何帮助将不胜感激。谢谢!
无法在您的 Service Worker 代码中派发 Redux 操作。
但是,您真正想要做的是使用 postMessage API 进行通信。使用 postMessage,当 SW 收到来自服务器的推送时,您可以向浏览器 JS 上下文发送一条消息。您可以找到更多信息,例如。这里https://developer.mozilla.org/en-US/docs/Web/API/Client/postMessage。
为什么会这样? 这是不同执行上下文的结果。您的普通 JS 代码(React、Redux、操作等)在“浏览器上下文”中运行,而您的服务代码在“软件上下文”中运行。这两个上下文不共享ANY变量或状态。因此,您无法在软件代码中调用任何函数(例如 Redux 操作)。您需要在两个上下文之间进行通信,然后在浏览器上下文中收到消息后,调用您想要的任何函数。 可能有点晚了,但我找到了解决方法。
首先我创建了一个简单的反应组件并初始化它们的套接字。import Cookies from 'js-cookie';
import React, { useEffect } from 'react';
import io, { Socket } from 'socket.io-client';
.......
.........
const ServiceWorker: React.FC = () => {
const dispatch = useTypedDispatch();
const authData = JSON.parse(Cookies.get('authData') || '{}');
useEffect(() => {
if (authData.accessToken) {
const connectionOpt = {
transports: ['polling'],
auth: { token: `Bearer ${authData.accessToken}` }
};
const socket: Socket = io(WS_URL, connectionOpt);
// Event listener for connection
socket.on('connect', () => {
console.log('web socket connected');
});
// Event listener for notification
socket.on('notification', (payload: INotification) => {
console.log('notification', payload);
dispatch(putNotification(payload));
});
// Event listener for disconnection
socket.on('disconnect', () => {
console.log('Disconnected');
});
// Clean up the socket connection when component unmounts
return () => {
socket.disconnect();
};
}
}, [authData.userId]); // Empty dependency array to ensure the effect runs only once
return (
<div>
{/* Your JSX content here if required*/}
</div>
);
};
然后只需将其导入到我的 App.tsx
<ErrorBoundary
FallbackComponent={() => <NotFound type="500" />}
>
<Router>
<Routes />
</Router>
<Toaster data-testid={`${APP_NAME}-toaster`} />
<ServiceWorker />
</ErrorBoundary>
对我来说效果很好。