私はangular2で始まったので、TのObservableを返すようにサービスをセットアップしました。サービスではmap()コールがあり、これらのサービスを使用するコンポーネントはsubscribe()応答を待ちます。これらのシンプルなシナリオでは、私は本当にrxjsを掘り下げる必要はありませんでした。rxjsを使ってリフレッシュトークンを扱う
私は今、次のことを達成したいと思います:リフレッシュトークンでOauth2認証を使用しています。他のすべてのサービスが使用するapiサービスを構築したいと思います。401エラーが返されたときにリフレッシュトークンを透過的に処理します。だから、401の場合は、まずOAuth2エンドポイントから新しいトークンを取り出し、新しいトークンでリクエストを再試行します。上記のコードで
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);
}
});
}
、authService.refreshAuthentication()新しいトークンを取得してのlocalStorageに保存します。以下は、約束して、正常に動作コードがあります。 authService.setAuthorizationHeaderは、 'Authorization'ヘッダーを以前に更新されたトークンに設定します。 catchメソッドを見れば、それは(そのリフレッシュトークンの)約束が最終的に(要求の実際の2回目の試みに対して)別の約束を返すという約束を返すことがわかります。私は約束に頼ることなく、これを行うことを試みてきた
:
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);
}
});
}
コードを上記の私は期待しません:200応答の場合には、それが適切に応答を返します。しかし、401を捕まえると、新しいトークンを正常に取得できますが、サブスクライブすると最終的にレスポンスではなくオブザーバブルが取得されます。これを推測しているImは再試行を行うべき実行されていないObservableです。
rxjsライブラリに取り組むという約束の方法を翻訳するのはおそらく最善の方法ではないと思いますが、「すべてがストリームです」ということを理解することはできませんでした。私はフラットマップ、retryWhenなどを含むいくつかの他のソリューションを試してみました...しかし、didntは遠くになるので、いくつかの助けに感謝します。
ハ:これは動作します:)私はflatMapメソッドを使ってみましたが、明らかに正しい方法ではありませんでした。サンクスポール! Ps:私がrxjsでかなり混乱しているのは、異なる名前のファイルでこれらのメソッドを隠す傾向があることです。 flatMapメソッドが機能するためには、私は "mergeMap"ファイルをインポートしなければなりません... – Davy
@Davy使用しているバージョンを尋ねることができますか? ReactiveXのプロジェクトであれば、まだベータ版になっているので、すべての機能が完了しているにもかかわらず、ドキュメンテーションは少し不足しています。 – paulpdaniels
これはhttps://github.com/ReactiveX/RxJS(「rxjs」npmパッケージ)です。 – Davy