我如何解析另一个 Observable 中的一个 Observable? - RXJS

How do I resolve an Observable inside of another Observable? - rxjs

我有一个 Observable,我在其中消耗了另一个可观察对象,但是第二个 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 函数 returns 和 Observable,但从未解决。我尝试添加一个flatMap和一个concat,但仍然没有解决。如何解决 getMe

下面的示例代码(未经测试!!)。一些解释:

  • getMe 编辑的 observable return 未被展平('resolve' 属于 promises 的世界)因为 map 运算符不会展平 observable。 flatMap 可以,但是您需要以 source.flatMap(function(x){return observable}) 的形式使用它,这里您 return 是 POJO 而不是 Rx.Observable.
  • 因此,为了压平 getMe,我们使用 flatMap
  • 为了添加缺失的字段(accessTokenrefreshToken),我们在发出 res 对象(res$)的 Observable 上使用 withLatestFrom .
  • 我们使用 share 因为我们订阅了两次 res$,我们希望所有订阅者看到相同的值。

    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'}));
    }
    

正如@user3743222 所指出的,Observable 并不像 Promise 那样 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
          };
        });

您是否尝试过以下方法(同样未经测试):

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));

如上post,flatMap returns一个observable。 map 随后用于将 res 与第二个承诺返回的结果 res2 合并。

还要注意 fromPromise 是一个冷可观察量。这意味着您必须订阅才能启动。在你的情况下,我想你已经有了这样的东西:

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

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