昂贵的不可变操作

Costly Immutable Operation

我的 redux 状态中有一个数据,大约有 100,000 json 条记录(每条记录有大约 8 个键值对)。

我在客户端编写了一个逻辑,每 30 秒刷新一次此数据(每 30 秒我调用服务器以获取要删除的记录和添加的记录)。

我在我的 reducer 函数中执行此处理,为此我编写了一个方法 "mergeUpdates" 遍历 state.data 对象来标识要删除的内容和插入的内容。

我使用不可变的 fromJs(state.data).toJs 来克隆 state.data 并进行更新(state.data 不是不可变的)。但是这个克隆结果是非常昂贵的操作(100,000 条记录大约需要 2 秒)因此我删除了克隆并开始修改 state.data 本身导致 "Assignment to function parameter" lint 错误,因为我正在修改的数据是被传递给一个函数。

initialState = {
  data: {}
}

doSomething(state, change) {
    // iterates on state and updates state
    state = doSomethingElse();
    return state;
}

mergeUpdates(state, change) {
   // some logic
   state = doSomething(state, change)

   // some more logic
   return state;
}


export default function (state=initialState, action) {
    switch (action.type) {
        case REFRESH: {
            return mergeUpdates(state.data, action.data)
        }
    }
}

处理这种情况的最佳做法是什么,我应该将状态分配给 "mergeUpdates" 和 "doSomething" 方法中的新引用以及 return 新引用,还是将我的数据内部状态是不可变的还是其他什么?

例如:这被认为是一种好的做法吗?

doSomething(state, change) {
    let newState = state; 

    // process change and return newState

    return newState; 
}

mergeUpdates(state, change) {
    let newState = state;

    // apply change on newState 
    newState = doSomething(newState, change);

   // return newState
   return newState;

}

Redux 本身并不强制用户使用普通对象进行状态管理。您可以使用不可变对象来存储数据,您唯一需要做的就是 re-inits fromJS 的全新状态,就像您上面所做的那样。 此外,immutable 必须在整个应用程序中使用。其实我建议你如果你的数据结构不复杂而不是笨重的不可变的,你可以使用扩展运算符来修改数据。 (对我来说,树下超过 3 级是复杂的)。

您应尽可能避免使用Immutable.js 的toJS()fromJS() 函数。根据其作者 Lee Byron,this are the most expensive operations in the library.

我建议寻找不同的方法。一些建议:

  • 如果您的数据已经在 Immutable.js 中,请使用它提供的其他功能来帮助更新该数据(例如 Map.withMutations()
  • 如果该数据尚未在 Immutable.js 中,或者您想避免使用它,您可能需要查看 one of the many immutable update libraries available,其中一些专门用于帮助将新值合并到现有的数据结构。