浏览器选项卡之间的Redux通信可实现乒乓效应(多路通信)

时间:2017-12-19 12:14:47

标签: 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 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;

Javascript: sharing data between tabsCommunication between tabs or windows

然而,我发现的所有解决方案都有一点问题。他们创造了乒乓球效应。因此,当选项卡存储更改时,将设置B选项卡存储,因为它从localstorage获取消息。但是,由于B标签存储发生了变化,因此它会触发相同的更改事件' (但有自己的信息),以前是由A标签发送的。因此,标签的存储空间将通过本地存储事件进行更改......所有内容都从头开始。

有没有更好的方法来处理信息的同步,其中:
- A可以向B [,C,D,...]发送消息; B可以向A [,C,D,...]发送消息;等
- 没有乒乓效应,
- 防止无限改变自己的存储空间。

2 个答案:

答案 0 :(得分:1)

以下可能会有效,它会在从另一个标签触发时创建一种特殊类型的操作:

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

答案 1 :(得分:1)

也许您可以尝试使用https://github.com/AOHUA/redux-state-sync,广播频道是在标签之间进行交流的更好方法。