并行承诺链,其间具有顺序动态内容

时间:2017-01-10 13:07:51

标签: javascript dynamic promise bluebird sequential

我无法理解这个问题如何将动态结果添加到承诺链中,如果可能的话,我可以随处查看。希望有人可以澄清或给我一个很好的解决方案,以便我试图完成以下示例(它是一个小型音乐播放器):

// API requests are done with a promise
let pfetch = (url) => Promise.resolve( $.ajax(...) )

// This will give me all playlists from a user
pfetch( 'USER-API-URL' )

    // The playlists i get have tracklists
    .then( results =>

        // When all playlists are fetched continue (Promise.all = parallel)
        Promise.all( results.playlists.map( playlist => pfetch(playlist.url) ) )
    )

    // Results of all playlists in arguments
    .then( playlists => 

        // Each playlist has tracks and next_url
        playlists.map( playlist => {

        /* playlist.tracks 
         * if (playlist.next_url) pfetch(playlist.next_url)
         * append results to playlist.tracks
         */

        })
    )

        //only continue if all all tracks are complete

    //can i do a Promise.join() in the previous step?
    .then( () => console.log('finished,yay!') )

某些曲目列表的响应中有next_url,这意味着我还应该获取属于曲目列表的下一个网址,这样我就可以获得完整的tracklist.tracks。但是,这必须是顺序的,因为我不知道响应中是否有后续的next_url。如果没有next_url我完成了一个曲目列表,并且可以对下一个曲目列表执行相同的操作(因此.map)。

所以我的问题,你如何在承诺中进行动态内容链接?我知道您可以使用reduce进行排序,但在这种情况下,next_url的数量并不固定。我已经考虑了递归,但还没有找到Promise.each的好例子。

提前竖起大拇指。

1 个答案:

答案 0 :(得分:1)

如果您创建一个递归处理播放列表网址的函数

var getPlaylistUrl = url => 
    pfetch(url).then(playlist => 
        playlist.next_url ? Promise.all([].concat.apply([playlist.tracks], getPlaylistUrl(playlist.next_url))) : playlist.tracks
    );

您应该能够按如下方式重写代码

pfetch('USER-API-URL')
.then(results => Promise.all(results.playlists.map(playlist => getPlaylistUrl(playlist.url))))
.then( playlists => {
    // playlists should be complete
})
.then( () => console.log('finished,yay!') );