I can't get my head around this problem how dynamic results can be added to a promise chain, i've looked everywhere if this is even possible. Hope someone can clarify or give me a good solution for the following example i'm trying to accomplish (it's a small music player):
// 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!') )
Some of the track lists have a next_url
in their response, meaning, i should also fetch the next url belonging to the track list, so i can get a complete tracklist.tracks
. However this has to be sequential as i don't know if there is a subsequent next_url
in the response. When there is no next_url
i'm finished with one track list and can do the same with the next (hence .map
).
So my question, how do you do this dynamic content chaining in promises? I know you can do sequencing with reduce
, but in this case the amount of next_url
's is not fixed. I've thought about recursion and yet to find a good example for Promise.each
.
Thumbs up in advance.
If you create a function to recursively deal with a playlist url
var getPlaylistUrl = url =>
pfetch(url).then(playlist =>
playlist.next_url ? Promise.all([].concat.apply([playlist.tracks], getPlaylistUrl(playlist.next_url))) : playlist.tracks
);
you should be able to rewrite your code as follows
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!') );