2017-01-19 5 views
0

私はRXJSでより良い処理をしようとしていますが、私はAudienceService.addAudience()を呼び出すとCannot read property 'map' of undefinedを取得しています。マップされた関数の後のAngular2 rxjs map()はサブスクライブハンドルを完了する

AuthHttpService.post()のサブスクリプションが完了する前に、AudienceServiceAuthHttpService.post()にマップしようとすると、トークンのリフレッシュが必要な場合があります。

これをコード化するにはどうすればいいですか?AuthHttpServiceが完了した後でmap()が実行されるようにするにはどうすればよいですか? AuthHttpService.postにマップ

AudienceService:POSTメソッドで

addAudience(model: AddDeleteAudienceModel) { 
    return this.authHttpService.post(this.baseApiUrl + 'audience', JSON.stringify(model)).map(res => res.json()); 
    } 

AuthHttpService:

post(endpoint: string, body: string) { 
    if (this.authService.tokenRequiresRefresh()) { 
     this.authService.tokenIsBeingRefreshed.next(true); 
     this.authService.refreshToken().subscribe(
     data => { 
      this.authService.refreshTokenSuccessHandler(data); 
      // The audience service post call returns "Cannot read property 'map' of undefined" 
      console.log("User is now logged in"); 
      if (this.authService.loggedIn()) { 
      this.authService.tokenIsBeingRefreshed.next(false); 
      return this.postInternal(endpoint, body); 
      } else { 
      this.authService.tokenIsBeingRefreshed.next(false); 
      this.router.navigate(['/sessiontimeout']); 
      } 
     }, 
     error => { 
      this.authService.refreshTokenErrorHandler(error); 
      Observable.throw(error); 
     } 
    ); 
    } 
    else { 
     console.log("HTTP Post token refresh not required."); 
     return this.postInternal(endpoint, body); 
    } 
    } 
+0

これを 'RxJs'からインポートしましたか? –

+0

@YashveerSinghはい、マップ自体がインポートされ、トークンのリフレッシュが必要な場合にのみ問題が発生します。それ以外の場合はマップが定義されます。 – blgrnboy

+0

authHttpServiceとは何ですか? –

答えて

4

あなたはそれがトークンをリフレッシュする必要があるときに正しくpost()は何も返しません述べたように。 subscribe()メソッド内のreturnステートメントは、トークンがリフレッシュされる前に関数が返すので呼び出されません。

subscribeコールの代わりにswitchMap()を使用します。この場合、elseブロック内からObservableを返す必要があります。ように:

post(endpoint: string, body: string) { 
    if (this.authService.tokenRequiresRefresh()) { 
     this.authService.tokenIsBeingRefreshed.next(true); 
     return this.authService.refreshToken().switchMap(
     data => { 
      this.authService.refreshTokenSuccessHandler(data); 
      // The audience service post call returns "Cannot read property 'map' of undefined" 
      console.log("User is now logged in"); 
      if (this.authService.loggedIn()) { 
      this.authService.tokenIsBeingRefreshed.next(false); 
      return this.postInternal(endpoint, body); 
      } else { 
      this.authService.tokenIsBeingRefreshed.next(false); 
      this.router.navigate(['/sessiontimeout']); 
      // return an Observable here otherwise you also get an undefined 
      } 
     }) 
     .catch((error) => { 
      this.authService.refreshTokenErrorHandler(error); 
      return Observable.throw(error); 
     }); 
    } 
    else { 
     console.log("HTTP Post token refresh not required."); 
     return this.postInternal(endpoint, body); 
    } 
    } 

詳細についてswitchMap()について基本的には、Observableの内側からObservableの外側に値をマッピングします。

+0

私はこの解決策が好きですが、次のエラーを返すようです: モジュールビルドに失敗しました:エラー:C:/src/USB.EnterpriseAutomation.AuthApi.UI/src/app/services/auth-http.service.ts 38,3):return式の中にはよくある共通型はありません。 – blgrnboy

+0

@blgrnboyは 'this.postInternal(endpoint、body)' Observableを返しますか? – chrigu

+0

はい、Observableを返します blgrnboy

1

投稿では、あなたは観察可能に戻る必要があります。私はこの作品が100%ではないと思っていますが、考え方はあなたが内部で見るよりも、観察可能なものを作り返すということです。あなたは例外

post(endpoint: string, body: string) { 
    if (this.authService.tokenRequiresRefresh()) { 
     this.authService.tokenIsBeingRefreshed.next(true); 
     return Observable.create((observer) => { 
      this.authService.refreshToken().subscribe(
       data => { 
        this.authService.refreshTokenSuccessHandler(data); 
        // The audience service post call returns "Cannot read property 'map' of undefined" 
        console.log("User is now logged in"); 
        if (this.authService.loggedIn()) { 
         this.authService.tokenIsBeingRefreshed.next(false); 
         this.postInternal(endpoint, body).subscribe(resp => { 
          observer.next(resp); 
         }) 

        } else { 
         this.authService.tokenIsBeingRefreshed.next(false); 
         this.router.navigate(['/sessiontimeout']); 
         observer.error(error); 
        } 
       }, 
       error => { 
        this.authService.refreshTokenErrorHandler(error); 
        observer.error(error); 
       } 
      ); 
     }); 


    } 
    else { 
     console.log("HTTP Post token refresh not required."); 
     return this.postInternal(endpoint, body); 
    } 
} 

私は私のアプリ

return Observable.create(observer => { 
     (<Promise<string>>token) 
      .then((tAsString) => { 
      super.request(this.getRequestOptionArgs(tAsString, request)) 
       .subscribe(response => { 
       observer.next(response); 
       // this emit error observer.error(eror) 
       }) 

      }) 
     }); 

PSの一部としてテストしている次の放出、または投げることができます。しかし、私はswitchMapはより良い選択肢です:)

+0

それはうまくいきますが、それはやや早く復帰したようです。私は 'addAudience'へのサブスクリプションですべての視聴者をリフレッシュしています。そのリフレッシュは追加を捕捉しません。次のリフレッシュでは、それは行います。 – blgrnboy

+0

私はそれを得ることができなかったあなたは説明してください:) –

関連する問題