Angular 2,在@ngrx/effects 中捕获 401

标签 angular ngrx

我的@ngrx/store 和 effects 工作正常,但是,我刚刚意识到会有很多 API 调用(在 effects 中),如果其中任何一个返回 401 错误,我应该将用户重定向到登录页面。我的问题是:我不想在每一个效果中都检查它,这将是同一件事的大量额外代码。比方说我有这样的代码:

示例效果

@Effect() getMe$ = this.actions$
    .ofType(GET_ME)
    .map(action => action.payload)
    .switchMap(payload => this.userService.me()
        .map(res => ({ type: GET_ME_SUCCESS, payload: res }))
        .catch(() => Observable.of({ type: GET_ME_FAILURE }))
    );

userService.me()

me(): Observable<User> {
  return this.apiService.get(`/auth/me`);
}

apiService.get()

get(endpoint: string): Observable<any> {
  return this.http.get(`${this.base}${endpoint}`, this.options())
    .map(res => res.json());
}

这工作得很好,但我不确定如何处理 API 返回 401 的情况。在这种情况下,我应该在哪里全局重定向用户?我应该为那个案例创建一个 Action 吗?那我应该在哪里发送那个 Action 呢?还是我做的完全错了?

如能提供正确方向的帮助,我们将不胜感激!

最佳答案

Http 发出的错误如果是从服务器接收到的错误,将包含一个 status 属性(设置为 HTTP 状态代码)。

如果您在基于 HTTP 的服务失败操作中包含错误状态:

@Effect() getMe$ = this.actions$
    .ofType(GET_ME)
    .map(action => action.payload)
    .switchMap(payload => this.userService.me()
        .map(res => ({ type: GET_ME_SUCCESS, payload: res }))
        .catch(error => Observable.of({
            type: GET_ME_FAILURE,
            payload: { errorStatus: error.status }
        }))
    );

然后您可以编写一个通用效果,查看所有操作,如果它们包含 401 错误则重定向:

@Effect() errorStatus401$ = this.actions$
    .map(action => action.payload)
    .filter(payload => payload && payload.errorStatus === 401)
    .switchMap(payload => {
        this.router.navigate(['/login']);
        return Observable.empty();
    });

或者,如果您使用 @ngrx/router-store :

import { go } from '@ngrx/router-store';
...

@Effect() errorStatus401$ = this.actions$
    .map(action => action.payload)
    .filter(payload => payload && payload.errorStatus === 401)
    .map(payload => go(['/login']));

如果您希望在导航之前执行其他操作,您可以使用 concat 发出多个操作:

@Effect() errorStatus401$ = this.actions$
    .map(action => action.payload)
    .filter(payload => payload && payload.errorStatus === 401)
    .switchMap(payload => Observable.concat({ type: 'CLEAR_TOKEN' }, go(['/login'])));

关于Angular 2,在@ngrx/effects 中捕获 401,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40442447/

相关文章:

redux - 如何在 ngrx/entity 的集合开头添加一个项目

javascript - ngrx 中的 store.select 是什么

angular - ngrx 8 : Access state of @ngrx/data entity from reducer function

typescript - NgRx:如何声明由 Action 创建者创建的 Action 的显式类型?

angular - 没有 InjectionToken 自定义 HTTP 配置的提供程序

css - Angular 6-在生产中未加载自定义CSS

Angular 获取当前路由

angular - 从商店的多个切片获取 NGRX 数据的最佳方法是什么

javascript - 响应式(Reactive) Angular 表单等待异步验证器在提交时完成

css - Angular 应用程序中的过渡动画在 EDGE 中不起作用