Angular2のHTTPクラスで認証失敗(401)を返すことができるサーバーを呼び出したいとします。リクエストでエラーをキャッチしてモーダルを開き、RxJSでモーダルが閉じるときに再試行する方法
要求の流れがそのようになっているはず:
ユーザーがmyService.getSomething()を使用してサーバーに要求を出し-
サーバーが401を返す場合)(
- を購読:開きますユーザーに彼の資格情報を求めるモーダルウィンドウ。
- ユーザーが正常にアプリケーション
- モーダルが閉じに再度ログインし は は(()myService.getSomething()。サブスクライブ)
ここで最初の要求を再試行する必要があり、コールバックで
export class MyService {
// ...
public getSomething(): Observable<Response> {
return this.http.get(url, options).catch((res: any, ob: any) => this.errorHandler(res, ob));
}
public errorHandler(res: Response, ob: Observable<any>): Observable<Response> {
if (res.status === 401) {
this.modalService.open(new ModalConfig({
content: LoginModalComponent,
close:() => { ob.retry(1); console.log("weow") } // <=close is the callback that should initiate the retry action on the initial request.
}));
}
else {
return Observable.throw(res.json());
}
}
}
doSomethingの()は、そのように使用されている:doSomething().map((r) => r.json()).subscribe((r) => ....)
更新1
@Thierry Templierのソリューションのように自分のコードを変更しました。
private errorHandler(res: Response, ob: Observable<any>): Observable<Response> {
if (res.status === 401) {
let closedSubject = new Subject();
this.modalService.open(new ModalConfig({
content: LoginModalComponent,
close:() => { closedSubject.next(res);} // I also tried .complete(), .next(null), .next(true), .next(false)
}));
return ob.retryWhen(() => closedSubject);
}
else {
return Observable.throw(res.json());
}
}
悲しいことに、それでもまだ動作しません。 retryWhenはすぐに実行され、closedSubject.next()が呼び出されるのを待機しません。したがって、オリジナルのObservable(getSomething()関数)をスパムする無限ループを開始します。
アップデート2
私は無限ループを示すためにplunkerを作成:
https://plnkr.co/edit/8SzmZlRHvi00OIdA7Bga
警告:plunkerを実行すると、文字列 '試験'
を使用してコンソールをスパムします更新3
ティエリーの正解に続いて、ソースフィールドが保護されているので、ソースフィールドを使用しない方法を見つけようとしました。 rxjsのissue trackerにフィールドを公開するように依頼した後、寄稿者はより良い解決策を提案しました。
public get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return super.get(url, options).retryWhen((errors: any) => this.errorHandler(errors));
}
private errorHandler(errors): any {
return errors.switchMap((err) => {
if (err.status === 401) {
let closedSubject = new Subject();
this.modalService.open(new ModalConfig({
content: LoginModalComponent,
close:() => { closedSubject.next(err); }
}));
return <any>closedSubject;
}
else {
return Observable.throw(err.json());
}
});
}
私はソースフィールドを使用する必要がないので、.catchの使用は避けてください。
これですべての作業は完了ですか? – user3743222
はい、動作します。 –