延迟observable返回值,直到我从角度5的HTTP请求得到结果

时间:2018-03-22 06:34:01

标签: angular rxjs observable angular5 angular-http-interceptors

我想延迟observable返回值,直到我从订阅的HTTP请求中获取new_token。我也在使用延迟时间,但我无法取得成功。

  

错误:返回未定义的值

     

预期:从服务器返回new_token

browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')

更新:正在消耗refresh_token的方法,我正在使用拦截器,401方法在

之下
  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);
}

4 个答案:

答案 0 :(得分:2)

请勿订阅post个请求,如果您想执行某些副作用,请改用do运算符。

if (token_refreshed) {
  return this.httplclient.post(...)
    .do(response => {
      localStorage...
    })
    .map(response => ...) // map the response to return only the new token?
    .delay(3000); // or maybe you don't need this?
}
return Observable.of(new_token).delay(3000);

答案 1 :(得分:0)

你不需要拖延。只要在值可用时传递该值,因为您无法确定该值在3000毫秒后是否可用。

  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();
}

更新:深入研究您的代码后,我已经做出了所需的更改。 BehavoiurSubjectSubject。尝试使用一次。

答案 2 :(得分:0)

如果我理解你想要实现的目标,我认为你应该重新组织你的代码,以便能够利用RxJs的Obsersable模式。

这是我的建议

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;

        return this.httplclient.post<UserToken>('/api/oauth/token', creds, { headers: headers })
// Do not subscribe here - rather chain operators to transform the Observable returned by http.post into what you really want to emit and return the Observable transformed
           .map(response => response.access_token)
           .do(token => localStorage.setItem('access_token', response.token))
           .do(token => console.log('I am returning', token)

}

如果你这样做,那么使用refreshToken()方法的人必须订阅返回的Observable并在那里管理结果,例如

this.tokenService.refreshToken()
.subscribe(
   token => {// do something with the token, maybe move here the localStore.setItem logic},
   err => {// handle the error condition}
)

答案 3 :(得分:0)

如果您必须等待归还令牌,为什么不使用Promise而不是Observable?

this.httplclient.post<UserToken>('/api/oauth/token', creds, { headers: headers }).toPromise().then((t: UserToken) => { 
   localStorage.setItem('access_token', t.access_token);
   new_token = t.access_token;
}).catch(() => {
   console.log("User authentication failed!");
});

如果您想在其他地方订阅更改,请使用主题。

// in your constructor
this.sub = new Subject();

// in your method to get the token
this.httplclient.post<UserToken>('/api/oauth/token', creds, { headers: headers }).toPromise().then((t: UserToken) => { 
   localStorage.setItem('access_token', t.access_token);
   new_token = t.access_token;
   this.sub.next(new_token);
}).catch(() => {
   console.log("User authentication failed!");
});

// getter for the subject
// use asObservable so other components can't use next(..) to push data
get tokenSub(): Observable<String> {
    return this.sub.asObservable();
}

// somewhere else
this.yourServer.tokenSub.subscribe((token: String) => {
    ....
}