La manipulation de l'actualisation des jetons à l'aide de rxjs

Depuis que j'ai commencé avec angular2 j'ai mis mes services pour retourner Observables de T. Dans le service, j'aurais la carte (appeler), et les composants à l'aide de ces services serait tout simplement utiliser subscribe() pour attendre la réponse. Pour ces scénarios simples, je n'ai pas vraiment besoin de creuser pour rxjs si tout était ok.

Je veux maintenant est le suivant: je suis à l'aide de l'authentification Oauth2 avec actualisation des jetons. Je veux construire une api de services que tous les autres services, et qui permettra de gérer de manière transparente l'actualisation jeton lorsqu'une erreur 401 est retourné. Ainsi, dans le cas d'un 401, j'ai d'abord chercher un nouveau jeton de la OAuth2 point de terminaison, puis réessayer ma demande avec un nouveau jeton. Ci-dessous est le code qui fonctionne très bien, avec des promesses:

request(url: string, request: RequestOptionsArgs): Promise<Response> {
    var me = this;

    request.headers = request.headers || new Headers();
    var isSecureCall: boolean =  true; //url.toLowerCase().startsWith('https://');
    if (isSecureCall === true) {
        me.authService.setAuthorizationHeader(request.headers);
    }
    request.headers.append('Content-Type', 'application/json');
    request.headers.append('Accept', 'application/json');

    return this.http.request(url, request).toPromise()
        .catch(initialError => {
            if (initialError && initialError.status === 401 && isSecureCall === true) {
                //token might be expired, try to refresh token. 
                return me.authService.refreshAuthentication().then((authenticationResult:AuthenticationResult) => {
                    if (authenticationResult.IsAuthenticated == true) {
                        //retry with new token
                        me.authService.setAuthorizationHeader(request.headers);
                        return this.http.request(url, request).toPromise();
                    }
                    return <any>Promise.reject(initialError);
                });
            }
            else {
                return <any>Promise.reject(initialError);
            }
        });
}

Dans le code ci-dessus, authService.refreshAuthentication() va chercher le nouveau jeton et de le stocker dans localStorage. authService.setAuthorizationHeader va définir le "Autorisation" de l'en-tête de déjà mis à jour jeton. Si vous regardez le catch méthode, vous allez voir qu'il renvoie une promesse (pour l'actualisation de jeton) que dans ses tours va finalement retourner une autre promesse (pour le 2ème essai de la demande).

J'ai essayé de le faire sans avoir recours à des promesses:

request(url: string, request: RequestOptionsArgs): Observable<Response> {
    var me = this;

    request.headers = request.headers || new Headers();
    var isSecureCall: boolean =  true; //url.toLowerCase().startsWith('https://');
    if (isSecureCall === true) {
        me.authService.setAuthorizationHeader(request.headers);
    }
    request.headers.append('Content-Type', 'application/json');
    request.headers.append('Accept', 'application/json');

    return this.http.request(url, request)
        .catch(initialError => {
            if (initialError && initialError.status === 401 && isSecureCall === true) {
                //token might be expired, try to refresh token
                return me.authService.refreshAuthenticationObservable().map((authenticationResult:AuthenticationResult) => {
                    if (authenticationResult.IsAuthenticated == true) {
                        //retry with new token
                        me.authService.setAuthorizationHeader(request.headers);
                        return this.http.request(url, request);
                    }
                    return Observable.throw(initialError);
                });
            }
            else {
                return Observable.throw(initialError);
            }
        });
}

Le code ci-dessus ne fait pas ce que j'attends: dans le cas d'une réponse 200, correctement renvoie la réponse. Toutefois, si elle l'attrape, la 401, il va réussir à récupérer le nouveau jeton, mais le abonnez-vous wil finalement récupérer un observables au lieu de la réponse. Im deviner que c'est la non Observables qui devrait faire le réessayer.

Je me rends compte que la traduction de la promesse de la façon de travailler sur le rxjs bibliothèque est probablement pas la meilleure façon d'aller, mais je n'ai pas été capable de saisir le "tout est un cours d'eau" de la chose. J'ai essayé quelques autres solutions impliquant flatmap, retryWhen etc ... mais il n'a pas été bien loin, donc, de l'aide est appréciée.

InformationsquelleAutor Davy | 2016-01-20