如何在不破坏Promise链的情况下处理Bluebird中的拒绝?

时间:2016-05-11 12:23:44

标签: javascript error-handling promise bluebird

假设我正在构建一个典型的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))
  1. 我们获得所有Feed
  2. 为每个Feed发出processFeed()
  3. 每集都会从processEpisode()
  4. 中发出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而不是真实结果。

    有没有一种优雅的方法来解决这些问题?我在Bluebird中查看finally语句,但我不确定这是最好的方法。

    谢谢!

1 个答案:

答案 0 :(得分:3)

只需将myRpackage::my_R_function处理程序直接放在.catch()上,这样您就可以在本地处理拒绝并将其转换为已解决的承诺,这将允许其他所有内容继续:

processFeed()

注意:您不需要额外的包装承诺。添加// 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()处理程序只会在拒绝承诺或抛出的情况下拒绝承诺。