Javascript 浏览器选项卡之间的重复通信产生乒乓球效果(多路通信)
我看到了很多关于如何使用Redux/JavaScript和localstorage在选项卡之间通信/共享数据的解决方案。比如:Javascript 浏览器选项卡之间的重复通信产生乒乓球效果(多路通信),javascript,redux,local-storage,Javascript,Redux,Local Storage,我看到了很多关于如何使用Redux/JavaScript和localstorage在选项卡之间通信/共享数据的解决方案。比如: import { applyMiddleware, createStore } from "redux"; import logger from "redux-logger"; import thunk from "redux-thunk"; import promise from "redux-promise-middleware"; import reducer
import { applyMiddleware, createStore } from "redux";
import logger from "redux-logger";
import thunk from "redux-thunk";
import promise from "redux-promise-middleware";
import reducer from "./reducers";
import {sourceId} from "./utils/helper";
const storageKey = 'redux-local-tab-sync';
function wrapAction(action) {
return {
action,
sourceId,
time: Date.now()
}
}
function storageMiddleware() {
return () => next => action => {
const wrappedAction = wrapAction(action);
localStorage.setItem(storageKey, JSON.stringify(wrappedAction));
next(action);
}
}
export function createStorageListener(store) {
return () => {
const wrappedAction = JSON.parse(localStorage.getItem(storageKey));
if (wrappedAction.sourceId !== sourceId) {
console.log(wrappedAction.action)
store.dispatch(wrappedAction.action);
}
}
}
const middleware = applyMiddleware(promise(), thunk, storageMiddleware(), logger());
const store = createStore(reducer, middleware);
window.addEventListener('storage', createStorageListener(store));
export default store;
或和
然而,我发现所有的解决方案都有一个小问题。它们产生了乒乓球的效果。因此,当一个选项卡存储发生更改时,将设置B选项卡存储,因为它从localstorage获取一条消息。但是,因为B选项卡存储是更改的,所以它会触发“相同的更改事件”(但带有自己的信息),该事件以前是由选项卡发送的。因此选项卡的存储将通过本地存储事件进行更改。。。一切都从一开始
是否有更好的方法来处理以下位置的信息同步:-A可以向B[,C,D,…]发送消息;B可以向a[,C,D,…]发送消息;etc
-不产生乒乓球效果,
-防止无限地更改自己的存储。可能以下操作会起作用,当从另一个选项卡触发时,它将创建一种特殊类型的操作:
function storageMiddleware() {
return () => next => action => {
if(action.type!=="from other tab"){
const wrappedAction = wrapAction(action);
localStorage.setItem(storageKey, JSON.stringify(wrappedAction));
}else{
action=action.data;
}
next(action);
}
}
export function createStorageListener(store) {
return () => {
const wrappedAction = JSON.parse(localStorage.getItem(storageKey));
if (wrappedAction.sourceId !== sourceId) {
console.log(wrappedAction.action)
store.dispatch({
type:"from other tab",
data:wrappedAction.action
});
}
}
}
也许您可以尝试一下,广播频道是在选项卡之间进行通信的更好方式。作为消息的一部分,设置包含“源”选项卡的属性。然后,您可以轻松地检查事件是否源自当前选项卡并忽略它。是的,我使用“sourceId”来执行此操作。但是,在相反的选项卡上,这是以同样的方式设置的,在它更新了自己的存储之后,它在那里设置了自己的“sourceId”,它会将A检测为新状态,但它是A自己的状态。实际上,我需要以某种方式防止在第
localStorage.setItem
行将接收到的事件发送/设置回localStorage。但我不知道那个事件是从哪里来的…这个图书馆太棒了。谢谢你。@anthony dandrea很高兴你喜欢它:)