4

我正在使用 aurelia 开发并使用 aurelia-store 进行应用程序状态管理。在从服务器加载数据时,我想更改 isLoading 字段 true/false 以在相关组件上显示掩码。所以我在我的状态下定义了一个属性isLoading(例如)。在加载操作中,我想首先将加载状态更改为 true,然后将数据检索到 false。因此,根据该字段(isLoading)的值,我想在组件上显示掩码。

我想要这样的东西:

export async function getRoles(state) {
  try {
    return Object.assign({}, state, { isRolesListLoading: {busy: true} });
    const getRoles = await accountManagement.getRoles();
    return Object.assign({}, state, { getRoles, isRolesListLoading: {busy: false} });

  } catch (error) {
    console.log('error getRoles "error": ', error);
  }
}

但正如我从 aurelia 文档中得出的那样,一个动作中不允许进行两种状态更改。

我应该怎么办?

我有一个想法,首先在这个动作中调度另一个动作,使 isLoading 为真,然后完成这项工作。像这样的东西:

export async function getRoles(state) {
  try {
    desiredDispatch('goToLoadingState'); // fake code
    const getRoles = await accountManagement.getRoles();
    return Object.assign({}, state, { getRoles, isRolesListLoading: {busy: false} });

  } catch (error) {
    console.log('error getRoles "error": ', error);
  }
}

但是我找不到一些关于如何在一个动作中调度另一个动作的文档。

有哪些可能的解决方案?

4

1 回答 1

5

我试图将您的问题简化为一个小样本,您可以在此处找到。

初始状态是这样的:

initialState: {
  roles: [],
  isLoading: false
}

如您所见,它有一个角色数组,应将要加载的角色存储到其中,并有一个isLoading布尔值以有条件地显示加载指示器。

现在我们已经设置了示例,让我们深入了解细节。

首先,从动作中远程加载数据是可行的,但应该小心。Aurelia Store 的调度管道是一个异步队列。这意味着新操作将在最后自动排队。现在,如果当前执行的操作需要很长时间才能解决,您可能会遇到 UI 滞后等问题,因为所有后续操作只会在以后更新。

其次,一个动作应该创建一个新状态。您实际上想要做的将包括 3 个动作。

  1. 打开加载指示灯
  2. 加载数据并更新商店
  3. 关闭加载指示灯

因此,在链接示例中,我建议按照以下方式进行操作:

export class App {
  ...

  async loadRoles() {
    // Activate the loader, await the action so you don't start loading before the new state is actually set
    await this.store.dispatch(setLoader, true);
    // Local to the function start loading the roles, so you don't block the action queue
    const roles = await loadRoles();
    // once the data is available update the roles
    await this.store.dispatch(updateRoles, roles);
    // once that is set disable the loader
    await this.store.dispatch(setLoader, false);
  }
}

async function loadRoles() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(["User role", "Admin role", "Superuser role"]);
    }, 1000);
  });
}

function setLoader(state, isLoading) {
  return Object.assign({}, state, { isLoading });
}

function updateRoles(state, roles) {
  return Object.assign({}, state, { roles });
}

现在这 3 个调度也可以减少到 2 个,因为设置数据和禁用加载器可以一次性完成。动作的好处在于,您可以创建一个新函数,通过从旧的两个函数中组合一个新函数来实现这一点。

function updateRolesAndDisableLoader(state, roles) {
  return Object.assign(
    {},
    updateRoles(state, roles),
    setLoader(state, false)
  );
}
于 2019-01-21T09:48:48.687 回答