2016-05-11 5 views
1

Angenommen, ich baue einen typischen RSS-Reader. Ich bin mehrere Feeds Parsen und schreiben alle ihre Folgen zu DB:Wie man Ablehnungen in Bluebird behandelt, ohne eine Promise-Kette zu brechen?

const processEpisode = (episode)=> 
    fetchMetadata(episode) 
    .then(parseMetadata) 
    .then(writeToDb) 

const processFeed = (feed)=> 
    fetchEpisodes(feed) // returns [Episode] 
    .map(processEpisode, { concurrency: 3 }) 

// main 
getFeeds() // returns [Feed] 
.map(processFeed, { concurrency: 3 }) 
.catch(err=> console.log(err)) 
  1. Wir alle bekommen die Feeds
  2. Für jeden Feed emittieren processFeed()
  3. Für jede Folge emittieren processEpisode() von processFeed()

Wenn jedoch fetchMetadata(episode) für eine Episode für einige Feeds eine Ablehnung wirft, alle die Kette ist gebrochen und fällt sofort in globale .catch(err=> console.log(err)).

In normalen Situation müssen wir etwas mit unbearbeiteten Episode tun, aber die am wenigsten sollte normal verarbeitet werden. Eine Lösung besteht darin, processEpisode() in ein äußeres Versprechen zu verpacken und an Ort und Stelle zu handhaben.

const processEpisode = (episode)=> 
    new Promise((resolve, reject)=> { 
    fetchMetadata(episode) 
    .then(parseMetadata) 
    .then(writeToDb) 
    .then((result)=> resolve(result)) 
    .catch((err)=> { 
     // something bad happened 
     // process and error, but resolve a fullfilled Promise! 
     resolve(true) 
    }) 
    }) 

Aber ich nehme an, es ist ein offensichtliches Anti-Muster. Und wenn es nach processEpisode() ein anderes Element in der Promise-Kette höherer Ebene gibt, wird es fehlschlagen, weil processEpisodetrue anstelle des realen Ergebnisses auflösen wird.

Gibt es eine elegante Möglichkeit, solche Probleme zu lösen? Ich habe durch finally Anweisung in Bluebird gesucht, aber ich bin mir nicht sicher, es ist der beste Weg.

Vielen Dank!

Antwort

3

Setzen Sie einfach einen .catch() Handler direkt auf processFeed() so können Sie die Ablehnung lokal verarbeiten und in ein Versprechen gelöst zuwenden, die sonst alles erlauben weiterhin:

// main 
getFeeds() // returns [Feed] 
.map(function(item, index, length) { 
    return processFeed(item, index, length).catch(function(reason) { 
     // do whatever you want to here, this will "handle" the rejection 
     // and turn it into a resolved promise 
     // whatever you return here will become the resolved value 
    }); 
}, { concurrency: 3 }) 
.catch(err=> console.log(err)) 

Hinweis: Sie müssen nicht die extra Verpackungsversprechen. Das Hinzufügen eines .catch()-Handlers und das Zurückgeben eines normalen Werts aus dem .catch()-Handler wird das abgelehnte Versprechen in ein gelöstes Versprechen umwandeln, da die Zurückweisung zu diesem Zeitpunkt als "behandelt" betrachtet wird. Welcher Wert auch immer Sie vom .catch()-Handler zurückgeben, wird zum aufgelösten Wert des übergeordneten Versprechens.

Ein .catch() Handler hält das Versprechen nur dann zurück, wenn es ein abgelehntes Versprechen oder eine Antwort zurückgibt.

+0

Versucht dies kurz vor Ihrem Kommentar, und es hat funktioniert :) Vielen Dank für die Bestätigung. Markieren Sie dies als gelöst. – f1nn

Verwandte Themen