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 в конце.
Я сделал это правильно? Или есть лучший способ справиться с этим?
Ответы
Ответ 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, вам необходимо импортировать этот класс в свой компонент и создать приватную переменную в конструкторе компонента и вызвать требуемое действие класса, где это необходимо. Но для меня лучше использовать тот пакет, который работает очень хорошо.