Angular 2、在@ngrx/effects中捕获401
Angular 2, catching 401 in @ngrx/effects
我有 @ngrx/store 并且效果很好,但是,我刚刚意识到会有很多 API 调用(在效果中),如果其中任何一个 returns 一个 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 return 401 时的情况。在这种情况下,我应该在哪里全局重定向用户?我应该为那个案例创建一个动作吗?那我应该在哪里发送那个动作呢?还是我完全错了?
如能提供正确方向的帮助,我们将不胜感激!
从 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'])));
我有 @ngrx/store 并且效果很好,但是,我刚刚意识到会有很多 API 调用(在效果中),如果其中任何一个 returns 一个 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 return 401 时的情况。在这种情况下,我应该在哪里全局重定向用户?我应该为那个案例创建一个动作吗?那我应该在哪里发送那个动作呢?还是我完全错了?
如能提供正确方向的帮助,我们将不胜感激!
从 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'])));