2015-12-09 11 views
5

私はObservableを持っていますが、私は別の観察可能なものを消費しますが、第2のObservableは解決できません。ここでは、コードは次のとおりです。Observable内の他のObservableをどのように解決するのですか? - rxjs

return Observable.fromPromise(axios(config)) 
     .map(res => { 
      return { 
       accessToken: res.data.access_token, 
       refreshToken: res.data.refresh_token     
      } 
     }) 
     .map(res => { 
      return { 
       me: getMe(res.accessToken), 
       accessToken: res.accessToken, 
       refreshToken: res.refreshToken     
      } 
     }) 

function getMe(accessToken) { 
    return Observable.fromPromise(axios.get({ 
     url: 'https://api.spotify.com/v1/me', 
    })); 
} 

getMe機能はObservableを返しますが、それが解決されることはありません。 flatMapconcatを追加しようとしましたが、まだ解決されていません。解決するためにgetMeを取得するにはどうすればよいですか?

答えて

8

あなたは(また、未テスト)以下を試してみました:

function getMe(accessToken) { 
    return Rx.Observable.fromPromise(axios.get({ 
    url: 'https://api.spotify.com/v1/me', 
    })); 
}  

Rx.Observable.fromPromise(axios(config)) 
    .map((res) => { 
     return { 
      accessToken: res.data.access_token, 
      refreshToken: res.data.refresh_token     
     } 
    }) 
    .flatMap((res) => { 
     return getMe(res.accessToken).map((res2) => { 
      res.me = res2; 
      return res; 
     } 
    }) 
    .subscribe((data) => console.log(data)); 

、観察を返しflatMap上記の記事で述べたように。 mapを使用してresを2番目の約束から返された結果res2にマージします。

また、fromPromiseは低温で観測可能です。つまり、物事を開始するには購読が必要です。あなたのケースでは、私はあなたがすでにこのような何か持っていると推測:

someFunction =() => { 
    return Rx.Observable.fromPromise(axios(config)) 
    ... 
    ... 
} 

someFunction.subscribe((data) => console.log(data)); 
+0

興味深い提案。それをテストする価値があるかもしれません。私の考えでは、クロージャから 'res'にアクセスする可能性のある問題があります。私はこれについてはわかりませんが、 'res。私の体は 'getMe'が値を出すときにのみ実行/評価され、' res'変数がまだその値を保持しているのか疑問です。私は、Observablesと関連して純粋な関数のみを使って、これを防衛的に記述します。私はあまりにも慎重であるかどうかを知ることに興味があります。 – user3743222

+0

クロージャの観点からは、 'res'はまだ値を保持しています(私は以前この手法を使っていました)。私は、コーディングの防衛スタイルを持ち、徹底的にテストすることがベストだと同意します。 'getMe()'が解決する前に 'Rx.Observable.fromPromise(axios(config))'実行が2番目にある場合、2つのサブスクライブ実行があります。これは 'flatMapLatest'を使うことで簡単に解決できます。これにより、1回のsubscribe実行で最新の' getMe() 'レスポンスを確実に得ることができます。 – Jeremy

+0

フェア十分です。説明をありがとう。 – user3743222

0

以下に見つけるサンプルコード(未テスト!)。いくつかの説明:mapオペレータが観測をフラット化していないため

  • getMeによって返され、観察が平坦化されていません(「決意は」約束の世界に属しています)。 flatMapですが、source.flatMap(function(x){return observable})の形式で使用する必要があります。ここで返すものはPOJOで、Rx.Observableではありません。
  • したがって、getMeをフラット化するには、flatMapを使用します。
  • オブジェクト(res$)を発行したオブザーバブルに、不足しているフィールド(accessTokenrefreshToken)を追加するにはwithLatestFromを使用します。
  • res$に2回購読するので、shareを使用します。すべてのユーザに同じ値が表示されるようにします。

    var res$ = Observable 
        .fromPromise(axios(config)) 
        .map(function (res) { 
         return { 
         accessToken : res.data.access_token, 
         refreshToken : res.data.refresh_token 
         } 
        }) 
        .share(); 
    var getMe$ = res$.flatMap(function (res) {return getMe(res.accessToken)}); 
    var finalRes$ = getMe$.withLatestFrom(res$, function (getMe, res) { 
    return { 
        me   : getMe, 
        accessToken : res.accessToken, 
        refreshToken : res.refreshToken 
    } 
    }); 
    
    function getMe (accessToken) { 
        return Observable.fromPromise(axios.get({url : 'https://api.spotify.com/v1/me'})); 
    } 
    
+0

をPOJO =平野旧JavaScriptオブジェクト – user3743222

+0

は協力いただきありがとうございますが、これは、 'Promises'を使用するよりも複雑なようです。より簡潔な方法が必要です。 – jhamm

+0

他の人が出てくるものを見てみましょう。質問:あなたが望む結果が得られたら、約束を使用して観察可能に変換するのはなぜですか? 'Rx.Observable.fromPromise'はそれを行います。そうすれば、あなたは両方の世界のベストを得ます。 – user3743222

2

@のuser3743222が指摘したように、ObservablePromiseがないという意味ではないresolveを行います。 getMeメソッドの値をご希望の場合は、Observableを返信する必要があります。

return Observable.fromPromise(axios(config)) 
     .map(res => { 
      return { 
       accessToken: res.data.access_token, 
       refreshToken: res.data.refresh_token     
      } 
     }) 
     .flatMap(function(tokens) { 

      //FlatMap can implicitly accept a Promise return, so I showed that here 
      //for brevity 
      return axios.get({url : 'https://api.spotify.com/v1/me'}); 
     }, 

     //The second method gives you both the item passed into the first function 
     //paired with every item emitted from the returned Observable` 
     //i.e. axios.get(...) 
     function(tokens, response) { 
      return { 
      accessToken: tokens.accessToken, 
      refreshToken: tokens.accessToken, 
      //Here response is a value not an Observable 
      me: response 
      }; 
     }); 
関連する問題