2017-01-10 4 views
1

Ich kann mich nicht um dieses Problem, wie dynamische Ergebnisse zu einer Versprechen Kette hinzugefügt werden kann, ich habe überall hin, wenn das überhaupt möglich ist. Hoffe jemand kann mir ich versuche klären oder gibt eine gute Lösung für das folgende Beispiel bin zu erreichen (es ist ein kleiner Musik-Player):Parallele Versprechen Kette mit sequentiellen dynamischen Inhalt zwischen

// 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!')) 

Einige der Titellisten ein next_url in ihrer Antwort, Bedeutung haben, i sollte auch die nächste URL aus der Trackliste holen, damit ich eine komplette tracklist.tracks bekommen kann. Dies muss jedoch sequentiell sein, da ich nicht weiß, ob es in der Antwort einen nachfolgenden next_url gibt. Wenn es keine next_url gibt, bin ich mit einer Titelliste fertig und kann das gleiche mit dem nächsten machen (daher .map).

Also meine Frage, wie machst du diesen dynamischen Inhalt Verkettung Versprechen? Ich weiß, dass Sie Sequenzierung mit reduce tun können, aber in diesem Fall ist die Menge von next_url 's nicht behoben. Ich habe über Rekursion nachgedacht und dennoch ein gutes Beispiel für Promise.each gefunden.

Daumen hoch im Voraus.

Antwort

1

Wenn Sie eine Funktion erstellen, um rekursiv mit einer Playlist url zu beschäftigen

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

sollten Sie in der Lage sein, den Code neu zu schreiben, wie

folgt
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!')); 
+0

gut. diese Art löst das Problem aber gibt es eine elegantere Problemumgehung oder ist eine rekursive Funktion der einzige Weg? – proxylittle

+0

Die Daten sind rekursiv in der Natur, Sie müssen durch sie "rekurriert": p. Was meinst du damit "löst das Problem" - gibt es dir das gewünschte Ergebnis oder nicht? –

+0

yeah, aber in '{results: [result.tracks, [result.tracks, [result.tracks, ...]]]]}} muss es abflachen, aber in der Tat ist Ihre Lösung in meiner Liste der Todos für die Annahme Antworten. Nur noch eine Frage, wenn es Ihnen nichts ausmacht. Wenn ich Daten im zweiten '.then (...)' Versprechen habe, gibt es eine Möglichkeit, das erste '.then (...)' über die Ergebnisse zu sagen oder lässt ein Versprechen das nicht zu? Ich hoffe immer noch auf diesen "schönen" Weg (perfektionistisch zu sprechen;)). – proxylittle

Verwandte Themen