ウェブサイト検索

javascript - Angular 4 インターセプターが 401 エラー時に各リクエストではなく一度だけトークンをリフレッシュする


トークンを更新したいです。インターセプターを使用しています:

アプリ.interceptor.ts

import { Observable } from 'rxjs';
import { Injectable, Inject, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { UserService } from "./user/services/user.service";

@Injectable()
export class AngularInterceptor implements HttpInterceptor {
    public userService;

    constructor(private injector: Injector) {
    }

    private applyCredentials = function (req) {
        return req.clone({
            headers: req.headers.set('Authorization', 'Bearer ' + localStorage.getItem('token'))
        });
    };

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.userService = this.injector.get(UserService);

        return next.handle(this.applyCredentials(req))
            /*.do(event => {
                if (event instanceof HttpResponse) {
                    console.log(event);
                }
            })*/
            .catch((res) => {
                console.log('Token refresh');

                if (res.status === 401 || res.status === 403 || res.status === 500) {
                    return this.userService.refreshToken().first().flatMap((data: any) => {
                        console.log(data.data);
                        if (data.data !== '') {
                            localStorage.removeItem('token');
                            localStorage.setItem('token', data.data);

                            this.userService.token = localStorage.getItem('token');
                            this.userService.isAuthenticated = true;
                        } else {
                            this.userService.logOut();

                            return Observable.throw(res);
                        }

                        return next.handle(this.applyCredentials(req));
                    });
                }
                /*else if (res.status === 500) {
                    this.userService.logOut();
                }*/

                return Observable.throw(res);
            });
    }
}

私のトークンはリフレッシュされており、動作しています。しかし、問題があります。複数のリクエストがある場合、私のトークンはリフレッシュされ、またリフレッシュされ、さらにリフレッシュされます。もしリクエストが3つあると、トークンは3回リフレッシュされます。

私の component.ts では:

Observable.forkJoin(
        this.countryService.getCountries(),
        this.movieService.getMovies(),
        this.userService.getUsers()
    ).subscribe(
        data => {
            console.log(data[0]);
            console.log(data[1]);
            console.log(data[2]);
            ...
            this.initPage();
        },
        err => console.error(err)
)

私のトークンは三回更新されました。すべてのリクエストを読み込み、その後で initPage() 関数を実行したいです。

私はトークンを一度だけ更新して、その後すべてのリクエストを再送したいです。