昂贵的不可变操作
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,其中一些专门用于帮助将新值合并到现有的数据结构。
我的 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,其中一些专门用于帮助将新值合并到现有的数据结构。