Aurelia Store单动作内两次变更状态的解决方案咨询
在Aurelia Store中处理加载状态的正确方式
你遇到的问题很典型——Aurelia Store的单个动作确实只能返回一次状态变更,所以第一个例子里return Object.assign({}, state, { isRolesListLoading: {busy: true} });之后的代码根本不会执行,这也是为什么你的加载状态永远不会变回false的原因。
好在Aurelia Store提供了在动作内部调度其他动作的能力,你只需要利用动作的第二个参数dispatch就可以实现需求。下面是两种可行的解决方案:
方案1:拆分动作,利用内部调度更新加载状态
首先,我们先定义一个专门用来设置加载状态的动作,保持单一职责:
// 单独的加载状态更新动作 export function setRolesListLoading(state, payload: { busy: boolean }) { return Object.assign({}, state, { isRolesListLoading: payload }); }
然后在你的数据获取动作里,通过dispatch参数先调用这个加载中动作,获取数据后再更新状态并重置加载状态:
export async function getRoles(state, dispatch) { try { // 先调度加载中状态 await dispatch(setRolesListLoading, { busy: true }); // 实际获取数据 const roles = await accountManagement.getRoles(); // 返回更新后的状态,同时将加载状态设为false return Object.assign({}, state, { roles, isRolesListLoading: { busy: false } }); } catch (error) { console.error('获取角色列表失败:', error); // 出错时也要记得重置加载状态,避免遮罩层一直显示 return Object.assign({}, state, { isRolesListLoading: { busy: false } }); } }
方案2:拆分数据更新和加载状态,完全用dispatch处理
如果希望把数据更新也拆成独立动作,让每个动作职责更清晰,可以这样做:
// 设置加载状态 export function setRolesListLoading(state, payload: { busy: boolean }) { return Object.assign({}, state, { isRolesListLoading: payload }); } // 更新角色列表数据 export function updateRoles(state, roles) { return Object.assign({}, state, { roles }); } // 主数据获取动作 export async function getRoles(state, dispatch) { try { await dispatch(setRolesListLoading, { busy: true }); const roles = await accountManagement.getRoles(); // 先更新数据,再重置加载状态 await dispatch(updateRoles, roles); await dispatch(setRolesListLoading, { busy: false }); // 这里返回原状态即可,因为状态变更已经通过dispatch完成 return state; } catch (error) { console.error('获取角色列表失败:', error); await dispatch(setRolesListLoading, { busy: false }); return state; } }
关键要点
- Aurelia Store的动作签名是
(state: T, dispatch: DispatchFunction, done: DoneFunction) => T | Promise<T>,第二个参数dispatch就是用来在动作内部调度其他动作的工具 - 一定要在成功和错误分支都重置加载状态,否则遇到错误时遮罩层会一直停留在页面上
- 拆分动作可以让代码更易维护,每个动作只负责一件事
内容的提问来源于stack exchange,提问作者Mohammad RN
相关产品推荐
相关产品推荐

