Подтвердить что ты не робот

Angular ngrx - Показать Загрузка gif

У меня есть побочный эффект:

@Effect()
FetchAllOrders$ = this.actions$
    .ofType(SalesOrderActions.FETCH_ALL_ORDERS)
    .switchMap((action: Action) => {
        return this.soApiService.getUsersSalesOrders(action.payload);
    })
    .map((salesOrders: ListDto<SalesOrderList>) => this.actions.fetchAllOrdersSuccess(salesOrders));

Я хотел бы показать символ загрузки в начале эффекта и скрыть его в конце.

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

export class BusyActions {
static SHOW_SPINNER = "SHOW_SPINNER";
static HIDE_SPINNER = "HIDE_SPINNER";

showSpinner(): Action {
   return { type: BusyActions.SHOW_SPINNER };
}

hideSpinner(): Action {
   return { type: BusyActions.HIDE_SPINNER };
}

export const BusyState: IBusyState = {
   visible: false,
   busy: false
};

Я сделал это так, потому что состояние загрузки должно делиться с другими модулями, состояниями и т.д.

Как я могу назвать свой BusyActions побочным эффектом? Мне нужно будет вызвать SHOW_SPINNER в начале и HIDE_SPINNER в конце.

Я сделал это правильно? Или есть лучший способ справиться с этим?

4b9b3361

Ответ 1

Возьмем пример: если вы хотите получить пользователя.

Что я обычно делаю для этого:
 - Отправка действия FetchUser
 - В редукторе установите флаг users: isUserFetching: true
 - Поймать это действие в эффекте
 - Позвоните, что вы хотите, например, услугу
 - Когда служба возвращает то, что он выбрал, сопоставьте это с действием успеха: FetchUserSuccess
 - Если что-то пошло не так, сопоставьте ошибку с действием ошибки: FetchUserError
 - В вашем редукторе пользователя, если для FetchUserSuccess выполните то, что вы хотите + установите isUserFetching: false
 - В вашем редукторе пользователя, если для FetchUserError выполните то, что вы хотите + установите isUserFetching: false

@Effect()
fetchUser$: Observable<Action> = this.actions$
  .ofType(FetchUser)
  .pipe(
    switchMap(action =>
      this.usersService.fetchUser(action.payload).pipe(
        map(
          res =>
            new FetchUserSuccess({
              id: action.payload.id,
              data: res,
            })
        ),
        catchError((err: HttpErrorResponse) => 
          of(new FetchUserError(action.payload))
        )
      )
    )
  );

В вашем представлении вы можете выбрать хорошую часть хранилища в переменной, скажем isFetchingUser$ и сделать:

<div *ngIf="isFetchingUser$ | async; else #loadingUser">
  Show the user here
</div>

<div loadingUser>
  Fetching user information
</div>

Ответ 2

Для этого вы можете использовать этот пакет npm https://www.npmjs.com/package/angular2-busy

После добавления всего необходимого модуля для использования пакета в вашем случае вам нужно объявить переменную

busy: Promise<any>; 

или

busy: Subscription;

И затем используйте эту переменную, как показано ниже

this.busy = this.actions$
.ofType(SalesOrderActions.FETCH_ALL_ORDERS)
.switchMap((action: Action) => {
    return this.soApiService.getUsersSalesOrders(action.payload);
})
.map((salesOrders: ListDto<SalesOrderList>) => this.actions.fetchAllOrdersSuccess(salesOrders));

Если вы хотите использовать свой класс busyActions, вам необходимо импортировать этот класс в свой компонент и создать приватную переменную в конструкторе компонента и вызвать требуемое действие класса, где это необходимо. Но для меня лучше использовать тот пакет, который работает очень хорошо.