angular2:仅获取和缓存令牌一次 [英] angular2: get and cache token only once

查看:62
本文介绍了angular2:仅获取和缓存令牌一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个"令牌"服务,该服务返回访问令牌.然后,我还有许多其他服务使用该服务获取访问令牌,然后它们才能使用请求标头中包含的令牌对后端进行API调用.

I have a "Token" service that returns an access-token. Then I have many other services that use this service to get an access-token before they can make an API call to the backend with the token included in the request header.

问题在于,其中许多服务几乎同时调用 Token 服务,因此在对令牌服务的第一个调用返回并被缓存"之前,将触发下一个调用.

The problem is that many of these services are calling the Token service almost simultaneously, so before the first call to the token service has returned and has been "cached" the next call is fired...

导致对后端的多次调用并获得多个令牌.

Resulting into multiple calls to the backend and getting multiple tokens.

有人可以告诉我如何停止对后端的多次呼叫.或者如何先运行令牌服务并缓存结果,然后才允许应用程序/服务运行/引导.

Can somebody please tell me how to stop the multiple calls to the backend. Or how to run the Token service before everything else and cache the result and only then allow the application/services to run/bootstrap.

我正在使用角度2.4.4

I'am using angular 2.4.4

感谢任何帮助/建议

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/toPromise';

export class Token{

    private cachedTokenObject = {
        'tokenKey':false,
        'userName':"johndoe@gmail.com",
        'password':"1234",
        'applicationId':"12344"
    };

    constructor(private _http: Http){}

    getAccessToken():Promise<Object>{

        if( this.cachedTokenObject.tokenKey ){
            console.log("returning chached token");
            return Promise.resolve( this.cachedTokenObject );
        }else{
            console.log("getting new token...");

            const tokenHeaders = "username=" + this.cachedTokenObject.userName + "&password=" + this.cachedTokenObject.password +"&grant_type=password";

            return this._http.post("https://someurl.com", tokenHeaders)
            .toPromise()
            .then( result => {
                if( result.json().hasOwnProperty('access_token') ){                 
                    this.cachedTokenObject.tokenKey = result.json()['access_token'];
                    return this.cachedTokenObject;
                }else{
                    console.log('"access_token" property not found in access object');
                    return {};
                }
            } )
            .catch(error =>{
                console.error('*** getAccessToken error ***', error);
                 Promise.reject(error);
            });
        }
    }
}


import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import { Headers, RequestOptions } from '@angular/http';
import {AccessTokenService} from './access-token.service';

@Injectable()
export class LanguageService{

    private cachedLanguages:any;

    constructor(private _http: Http, private _accessTokenService:AccessTokenService){}

    getLanguages(){

        return this._accessTokenService.getAccessToken().then( token => {

            if(this.cachedLanguages){
                console.log('returning cached languages', this.cachedLanguages);
                return Promise.resolve(this.cachedLanguages);
            }else{

                let headers = new Headers({ 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + token['tokenKey']});
                let options = new RequestOptions({ headers: headers });

                return this._http.get('https://someUrl/languages', options)
                .toPromise()
                .then(resp => {
                    this.cachedLanguages = JSON.parse( resp.json() );

                    return this.cachedLanguages;
                })
                .catch(error =>{
                    console.error('*** LanguageService error ***', error);
                     Promise.reject(error);
                });
            }
        });
    }
}

推荐答案

我有一个类似的问题,我使用RxJs运算符解决了.这是我的解决方案:

I had a similar issue and I solved it using RxJs operators. Here is my solution:

  private postRequest(): Observable<any> {
    let data: URLSearchParams = new URLSearchParams();
    let obs = this.http.postWithHeaders(
        'token', data, { 'Content-Type': 'application/x-www-form-urlencoded' })
        .map((response) => {
            ...
        })
        .catch((error) => {
           ...
        });
    return obs;
}

postRequest负责检索刷新令牌.请务必注意,它返回一个可观察值.

The postRequest is responsible for retrieving a refresh token. It's important to note that it returns an observable.

在构造函数中,我创建一个可观察的对象,该对象将推迟postRequest并共享我的可观察对象:

In the constructor I create an observable that will defer the postRequest and I share my observable:

 this.source = Observable.defer(() => {
        return this.postRequest();
    }).share();

共享运营商将在多个订阅者之间共享订阅.以下是更好地了解它的有用信息: RxJs-入门

The share operator will share the subscription between multiple subscribers. Here is a usefull to better understand it: RxJs - getting started

然后我创建了一个执行可观察的方法:

I then created a method that executes the observable:

refreshToken(): Observable<any> {
    return this.source
        .do((data) => {
            //extract the access token and save it to local storage
        }, error => {
           ...
        });
}

您可以通过多次订阅refreshToken方法,然后计算浏览器发出的请求数来测试代码:

You can test the code by subscribing to the refreshToken method multiple times and then counting the number of requests the browser makes:

this.tokenRefreshService.refreshToken().subscribe(x=>{...})
this.tokenRefreshService.refreshToken().subscribe(x=>{...})
this.tokenRefreshService.refreshToken().subscribe(x=>{...})

希望如此.

这篇关于angular2:仅获取和缓存令牌一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆