Aurelia在一次动作中两次更改状态 [英] Aurelia change state twice in one action

查看:93
本文介绍了Aurelia在一次动作中两次更改状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am developing with aurelia and using aurelia-store for app state management. On loading data from server, I want to change an isLoading field true/false to show mask on related components. So I have defined a property in my state isLoading (for example). In the loading action I want first change the loading state to true and after data retrieved to false. So that according to the value of this field (isLoading) I want to display the mask over component.

我想要这样的东西:

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文档中得出的那样,两个状态

but as I have figured from aurelia documentations, two state changes are not permitted in one action.

我该怎么办?

我有一个主意要发送此操作中的另一个操作首先要使isLoading为true,然后再执行此工作。像这样的东西:

And I have an idea to dispatch another action in this action first to make isLoading true and then do the job. Something like this:

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);
  }
}

但是我找不到一些有关如何

But I can't find some documentation on how to dispatch another action in one action.

可能的解决方案是什么?

What are the possible solutions?

推荐答案

我已尝试将您的问题简化为一个小示例,您可以在此处找到。

I've tried to dummy down your question to a small sample, which you can find over here.

initialState是这样的:

The initialState is like this:

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

如您所见,它具有一个角色数组,应将要加载的角色存储在其中,并使用 isLoading 布尔值有条件地显示加载情况指示符。

As you can see it has a roles array, where the to-be-loaded roles should be stored into and an isLoading boolean to conditionally show a loading indicator.

现在我们已经设置好样本,可以深入研究细节。

Now that we've setup the sample lets dive into the details.

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

First of all loading data remotely from within an action is doable but should be done with care. The dispatch pipeline of Aurelia Store is an async queue. That means new actions will automatically be queued at the end. Now if the action currently executed takes long to resolve, you'll might experience issues with lagging UI etc, since all subsequent actions only get updated later.

第二,一个操作应该创造一个新的状态。您实际上想要执行的操作将包括3个操作。

Second, an action is supposed to create one new state. What you would want to do actually would consist of 3 actions.


  1. 打开加载指示器

  2. 加载数据并更新商店

  3. 关闭加载指示器

因此已链接例如,我建议按以下方式进行操作:

So as in linked example, I'd propose to do it the following way:

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,因为设置数据并禁用装载机可以一炮打响。关于动作的好处是,您可以创建一个新功能,该功能可以通过将旧两个中的一个组成一个新功能来实现此功能。

Now those 3 dispatches could also be reduced to 2, since setting data plus disabling the loader could go in one shot. The nice thing about actions is that you can create a new function which does exactly that by composing a new out of the old two.

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

这篇关于Aurelia在一次动作中两次更改状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆