[英]How to handle rejections in Bluebird without breaking a Promise chain?
假設我正在構建一個典型的RSS閱讀器。 我正在解析幾個feed並將所有劇集寫入DB:
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))
processFeed()
processFeed()
發出processEpisode()
processFeed()
但是,如果針對某些Feed的某些劇集的fetchMetadata(episode)
引發拒絕,則所有鏈都會被破壞並立即進入全局.catch(err=> console.log(err))
。
在正常情況下,我們需要對未經處理的劇集做一些事情,但最少應該正常處理。 一種解決方案是將processEpisode()
包裝在外部Promise中並就地處理。
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)
})
})
但是,我認為這是一個明顯的反模式。 如果在processEpisode()
之后在更高級別的Promise鏈中有另一個元素,它將失敗'因為processEpisode
將解析true
而不是真實結果。
有沒有一種優雅的方法來解決這些問題? 我一直在尋找藍鳥的finally
聲明,但我不確定這是最好的方式。
謝謝!
只需將一個.catch()
處理程序直接放在processFeed()
這樣就可以在本地處理拒絕並將其轉換為已解決的promise,這將允許其他所有內容繼續:
// 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))
注意:您不需要額外的包裝承諾。 添加.catch()
處理程序,並從返回正常值.catch()
處理程序將打開拒絕承諾為解決承諾作為拒絕被認為是“處理”在這一點上。 無論從.catch()
處理程序返回什么值, .catch()
成為父承諾的已解析值。
.catch()
處理程序只會在拒絕承諾或拋出時拒絕承諾。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.