背景
一段时间以来,我一直在思考如何在Redux 中通过服务器交互(通过 ajax)实现撤消/重做。
我提出了一个使用命令模式的解决方案,其中操作使用execute
和undo
方法注册为命令,而不是调度操作,而是调度命令。然后将命令存储在堆栈中并在需要时引发新操作。
我当前的实现使用中间件来拦截调度、测试命令和调用命令的方法,看起来像这样:
中间件
let commands = [];
function undoMiddleware({ dispatch, getState }) {
return function (next) {
return function (action) {
if (action instanceof Command) {
// Execute the command
const promise = action.execute(action.value);
commands.push(action);
return promise(dispatch, getState);
} else {
if (action.type === UNDO) {
// Call the previous commands undo method
const command = commands.pop();
const promise = command.undo(command.value);
return promise(dispatch, getState);
} else {
return next(action);
}
}
};
};
}
行动
const UNDO = 'UNDO';
function undo() {
return {
type: UNDO
}
}
function add(value) {
return (dispatch, getState) => {
const { counter } = getState();
const newValue = counter + value;
return new Promise((resolve, reject) => {
resolve(newValue); // Ajax call goes here
}).then((data) => {
dispatch(receiveUpdate(data));
});
}
}
function sub(value) {
return (dispatch, getState) => {
const { counter } = getState();
const newValue = counter - value;
return new Promise((resolve, reject) => {
resolve(newValue); // Ajax call goes here
}).then((data) => {
dispatch(receiveUpdate(data));
});
}
}
命令
class Command {
execute() {
throw new Error('Not Implemented');
}
undo() {
throw new Error('Not Implemented');
}
}
class AddCommand extends Command {
constructor(value) {
super();
this.value = value;
}
execute() {
return add(this.value);
}
undo() {
return sub(this.value);
}
}
应用程序
const store = createStoreWithMiddleware(appReducer);
store.dispatch(new AddCommand(10)); // counter = 10
store.dispatch(new AddCommand(5)); // counter = 15
// Some time later
store.dispatch(undo()); // counter = 10
(这里有一个更完整的例子)
我在当前的方法中发现了几个问题:
- 由于通过中间件实现,整个应用程序可能只存在一个堆栈。
- 无法自定义
UNDO
命令类型。 - 创建一个命令来调用动作,而动作又返回Promise似乎非常复杂。
- 命令会在操作完成之前添加到堆栈中。错误会发生什么?
- 由于命令未处于状态,因此无法添加 is_undoable 功能。
- 您将如何实现乐观更新?
帮助
那么我的问题是,有人可以提出在 Redux 中实现此功能的更好方法吗?
我现在看到的最大缺陷是在操作完成之前添加的命令,以及向组合添加乐观更新是多么困难。
任何见解表示赞赏。