Аурелия дважды меняет состояние за одно действие - PullRequest
0 голосов
/ 19 января 2019

Я работаю с 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);
  }
}

но, как я понял из документации аурелии, два изменения состояния не допускаются в одном действии.

Что мне делать?

И у меня есть идея направить еще одно действие в этом действии, чтобы сделать isLoading true, а затем выполнить эту работу. Примерно так:

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

Но я не могу найти документацию о том, как отправить другое действие в одно действие.

Каковы возможные решения?

1 Ответ

0 голосов
/ 21 января 2019

Я пытался свести ваш вопрос к небольшой выборке, которую вы можете найти более здесь .

InitialState выглядит следующим образом:

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

Как вы можете видеть, он имеет массив ролей, в который должны быть сохранены загружаемые роли, и логический isLoading для условного отображения индикатора загрузки.

Теперь, когда мы настроили образецдавайте углубимся в детали.

Прежде всего, загрузка данных удаленно из действия возможна, но должна выполняться с осторожностью.Отгрузочный конвейер Aurelia Store представляет собой асинхронную очередь.Это означает, что новые действия будут автоматически поставлены в очередь в конце.Теперь, если выполняемое в настоящий момент действие занимает много времени, у вас могут возникнуть проблемы с запаздывающим пользовательским интерфейсом и т. Д., Поскольку все последующие действия обновляются только позже.

Во-вторых, действие должно создать одно новое состояние.То, что вы хотели бы сделать на самом деле, состояло бы из 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)
  );
}
...