Angular ngrx - 显示加载gif

17

我的副作用类似这样:

@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。

我这样做正确吗?或者有更好的处理方法吗?


你的Spinner会在整个应用程序的顶部吗?还是只在特定组件上方? - Deblaton Jean-Philippe
@DeblatonJean-Philippe,不确定你的意思是什么,但我猜整个应用程序。 - user2859298
2个回答

20

让我们来举一个例子:如果你想获取一个用户。

我通常会这样做:
- 分发一个动作 FetchUser
- 在 reducer 中,在 users 上设置一个标志:isUserFetching: true
- 在 effect 中捕获该动作
- 调用你想要的东西,比如一个服务
- 当服务返回它所获取的内容时,将其映射到成功的动作:FetchUserSuccess
- 如果出现错误,将错误映射到错误动作:FetchUserError
- 在您的用户 reducer 中,如果是 FetchUserSuccess,则执行您想要的操作 + 设置 isUserFetching: false
- 在您的用户 reducer 中,如果是 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>

+1 这是最佳的方法。将调用分为3个动作:加载、成功、失败。在您的状态中有一个名为“isLoading”的属性。在“Load”效果中调用API,然后映射到分派“Success”或“Fail”操作。 - Eeks33
@Maxime,如果您从另一个页面导航到用户页面,最好的位置来调度FetchUser操作是什么? - Taras Hupalo

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类,那么你需要在你的组件中引入这个类并在组件构造函数里创建一个私有变量,在必要时调用该类的所需操作。但对我来说,最好使用上面提到的包,它的效果非常好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接