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

Why do I have to indicate the index in my Rx stream?

我正在使用 knex 调用数据库,然后使用该结果与 axios 进行 REST 调用。我正在使用 rx 中的 Observables 来管理整个事情。这是我的代码,它没有像我想要的那样工作:

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

我不得不在 map 中使用 index,我调用 getCreatePlaylistConfig 来使代码工作。我注销了从 knex 调用返回的对象:

do(res => console.log(res)

看起来像这样:

[ { user_name: 'joe'} ]

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

问题是您的代码没有展平 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'
    }
}