web-dev-qa-db-ja.com

別のObservable内のObservableを解決するにはどうすればよいですか? -rxjs

Observableがあり、別のオブザーバブルを消費していますが、2番目のObservableを解決できません。コードは次のとおりです。

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を解決するにはどうすればよいですか?

7
jhamm

次のことを試しましたか(これもテストされていません):

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番目のpromiseから返された結果res2とマージするために使用されます。

また、fromPromiseは寒冷観測量であることに注意してください。これは、物事を開始するにはサブスクリプションが必要であることを意味します。あなたの場合、私はあなたがすでにこのようなものを持っていると思います:

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

someFunction.subscribe((data) => console.log(data));
8
Jeremy

@ user3743222が指摘したように、Observableは、resolveが行うという意味でPromiseを行いません。 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
          };
        });
2
paulpdaniels

以下にあるサンプルコード(未テスト!!)。いくつかの説明:

  • getMe演算子はオブザーバブルをフラット化しないため、mapによって返されるオブザーバブルはフラット化されません(「resolve」はpromiseの世界に属します)。 flatMapは実行しますが、source.flatMap(function(x){return observable})の形式で使用する必要があります。ここで返すのは、Rx.ObservableではなくPOJOです。
  • したがって、getMeを平坦化するには、flatMapを使用します。
  • 欠落しているフィールド(accessTokenおよびrefreshToken)を追加し直すには、withLatestFromオブジェクト(res$)を発行したオブザーバブルでresを使用します。
  • 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
user3743222