Search code examples
angularrxjsobservableangular5angular-http-interceptors

delay observable to return value until i get result from my HTTP request in angular 5


I want to delay observable to return value until i get new_token from my HTTP request in subscription. I am also using delay time but i could not able to success .

Error: returning undefined value

Expected: new_token returned from server

  refreshToken(): Observable<string> {

    const token_refreshed = localStorage.getItem("refresh_token");
  
    let new_token: string;
    if (token_refreshed) {
        console.log("this refreshed token" + token_refreshed);

        const headers = new HttpHeaders({
            'Authorization': "Basic " + btoa("clientId:client-secret"),
            'Content-Type': 'application/x-www-form-urlencoded',
            'grant_type': 'refresh_token',
            'refresh_token': token_refreshed
        });
        var creds = "grant_type=refresh_token" + "&credentials=true" + "&refresh_token=" + token_refreshed;

        this.httplclient.post<UserToken>('/api/oauth/token', creds, { headers: headers })
            .subscribe(response => {
               

                localStorage.setItem('access_token', response.access_token);
             
                new_token = response.access_token;
               
            }, err => {
                console.log("User authentication failed!");
            });
    }
    console.log('i am returning');
    return Observable.of(new_token).delay(3000);
}

Update: Method that is consuming refresh_token , I am using interceptor so, 401 method is below

handle401Error(req: HttpRequest<any>, next: HttpHandler) {
    if (!this.isRefreshingToken) {
        this.isRefreshingToken = true;
        console.log('I am handler 401');
        // Reset here so that the following requests wait until the token
        // comes back from the refreshToken call.
        this.tokenSubject.next(null);

        return this.authService.refreshToken()
            .switchMap((newToken: string) => {
                console.log('map token' + newToken);
//I'm getting null new token here from authService.refreshToken()           
              if (newToken) {
                    this.tokenSubject.next(newToken);


                    return next.handle(this.addToken(req, newToken));

                }

                return this.logoutUser();
            })
            .catch(error => {

                console.log('bad news its catch');
                return this.logoutUser();
            })
            .finally(() => {
                this.isRefreshingToken = false;
            });
    } else {
        return this.tokenSubject
            .filter(token => token != null)
            .take(1)
            .switchMap(token => {
                console.log('i am switch map else ');
                return next.handle(this.addToken(req, token));
            });
    }
}

Solution

  • You dont need to put a delay. Just pass the value whenever it is available because you can't be sure the value is available after 3000 ms.

      refreshToken(): Observable<string> {
        const tokenObsr = new Subject<string>();
        const token_refreshed = localStorage.getItem("refresh_token");
    
        if (token_refreshed) {
            console.log("this refreshed token" + token_refreshed);
    
            const headers = new HttpHeaders({
                'Authorization': "Basic " + btoa("clientId:client-secret"),
                'Content-Type': 'application/x-www-form-urlencoded',
                'grant_type': 'refresh_token',
                'refresh_token': token_refreshed
            });
            var creds = "grant_type=refresh_token" + "&credentials=true" + "&refresh_token=" + token_refreshed;
    
            this.httplclient.post<UserToken>('/api/oauth/token', creds, { headers: headers })
                .subscribe(response => {
    
    
                    localStorage.setItem('access_token', response.access_token);
    
                    tokenObsr.next(response.access_token);
    
                }, err => {
                    console.log("User authentication failed!");
                });
        }
        console.log('i am returning');
        return tokenObsr.asObservable();
    }
    

    Update: after looking deep into your code i have made the requried changes. BehavoiurSubject to Subject. Try using it once.