为什么我必须在我的Rx流中指明索引?

时间:2015-12-03 23:35:28

标签: rxjs

我呼叫knex的数据库,然后使用该结果与REST进行axios通话。我正在使用Observable中的rx来管理整个事情。这是我的代码无法正常工作:

return Observable
        .fromPromise(knex('users').where({id: userId}).select('user_name'))
        .map(res => getCreatePlaylistConfig(res[0].user_name))
        .concatMap(axios)
        .toPromise();

function getCreatePlaylistConfig(userName) {
    return {
        url: 'https://api.spotify.com/v1/users/' + userName + '/playlists',
        method: 'POST'
    }
}

我必须使用index中的map来调用getCreatePlaylistConfig来使代码正常工作。我使用:

注销了从knex调用回来的对象

do(res => console.log(res)

它看起来像这样:

[ { user_name: 'joe'} ]

这是一个像我期望的数组,但我认为map将遍历数组。为什么需要index?如何使此代码正常工作?

1 个答案:

答案 0 :(得分:2)

问题是您的代码没有展平Promise的结果。当您使用fromPromise时,您实际上是说要创建一个Observable来发出单个值,然后完成(如果您查看fromPromise的来源,这正是它的作用)。在您的情况下,单个值是一个数组。

map运算符将对从源Observable发出的每个值以及 map 它对另一个值起作用。但是,它不会尝试压平这些数据,因为这样做会相当冒昧。

如果你想避免明确使用索引操作符,你需要使用一个操作符来代替它。

return Observable
        .fromPromise(knex('users').where({id: userId}).select('user_name'))
         //flatMap implicitly converts an array into an Observable
         //so you need to use the identity function here
        .flatMap(res => res, 
                  //This will be called for each item in the array
                 (res, item) => getCreatePlaylistConfig(item.userName))
        .concatMap(axios)
        .toPromise();

function getCreatePlaylistConfig(userName) {
    return {
        url: 'https://api.spotify.com/v1/users/' + userName + '/playlists',
        method: 'POST'
    }
}