【问题标题】:Promise reject not working inside of callback承诺拒绝在回调内部不起作用
【发布时间】:2016-10-14 18:42:05
【问题描述】:

我正在编写一个使用 Google API 的模块,但是我将所有基于回调的东西都包装在一个 Promise 中。这是问题区域的代码

file1.js

var File2 = require('file2')
var api = new File2()
api.auth().then(auth => {
  api.search('example').then(res => {
     ...do some stuff...
  })
}).catch(err => {
  console.log('1') //Not being run
  throw err
})

file2.js

class File2(){
  auth() {
    ...works fine and resolves...
  }

  search() {
     return new Promise((resolve, reject) => {
       googleapi.somemethod(options, (err, res) => {
         if(err) { 
           console.log('2') // DOES run
           reject(new Error(err))
         }
         resolve(res.field) //Program crashes here because reject didn't actually reject
       })
     })

}

auth 的调用工作正常,但对search(更具体地说是googleapi.somemethod)的调用失败,并且err 已定义。我检查错误,然后console.log('2') 运行,但随后catch 中的console.log('1') 没有运行,没有抛出错误,并且程序在resolve(res) 上崩溃,因为res 未定义。我尝试将错误捕获器作为then 的第二个参数,而不是使用catch,但这仍然不起作用

api.search('example').then(res => {
  ...do some stuff...
 }, err => {
    console.log('2') // Still doesn't run
    throw err
 })

我正在运行 Node v6.2.1

【问题讨论】:

  • 你不应该return承诺吗?也不应该有else 吗?看起来resolve 无论如何都会被调用...
  • 我没有兑现承诺吗?我从来没有见过有人这样做 > return resolve() 或 >return reject() 至于其他,你可能是对的。我正在遵循处理返回某些内容的回调的常见模式,但是是的,这可能不适用于 Promise。尽管“解决”和“拒绝”有点像回归,但我一直在脑海中浮现,但这可能只是我对承诺的认识中的一个漏洞。
  • 检查我的答案,希望对您有所帮助。另外,不要介意else 部分。

标签: javascript node.js error-handling callback promise


【解决方案1】:

调用reject()不会停止你的程序,下面的所有代码也会被执行。

请更新

if(err) { 
  console.log('2') // DOES run
  reject(new Error(err))
}
resolve(res.field) //Program crashes here because reject didn't actually reject

if(err) { 
  console.log('2') // DOES run
  reject(new Error(err))
}
else {
  resolve(res.field) //Program crashes here because reject didn't actually reject
}

* 更新 * 或者您可以将代码缩短为

if(err) { 
  console.log('2') // DOES run
  return reject(err) // no need to new Error object
}
resolve(res.field) //Program crashes here because reject didn't actually reject

【讨论】:

  • 我也想过这个,但事实并非如此,因为promise只能处于一种状态。如果拒绝,则无法解决。我仍然会用else 写它,因为它使流程更清晰。
  • 或者你可以按照我在@elclanrs 上面更新的第二个解决方案
  • 是的,这是另一种更清晰的选择,但重点仍然存在,一旦您拒绝,将不会调用 resolve。见jsfiddle.net/g8yufxfa
【解决方案2】:

你应该返回承诺:

var File2 = require('file2')
var api = new File2()
api.auth().then(auth => {
  return api.search('example').then(res => { // return the promise
     return ...
  })
}).catch(err => {
  console.log('1') // Not being run
  throw err
})

另外,如果你不需要 authsearch 中,那么你可以取消这些承诺:

var File2 = require('file2')
var api = new File2()
api.auth().then(auth => {
  return api.search('example')
}).then(res => {
   return ...
}).catch(err => {
  console.log('1') //Not being run
  throw err
})

【讨论】:

  • 按照你说的做之后,catch 内部的console.log 正在运行,但throw err 并没有使程序崩溃。知道为什么会这样吗?
  • throw 不应该让你的程序在 promise 内崩溃,这是设计使然。在 Promise throw err === return Promise.reject(err) 中,因此您将在稍后的 .catch() 处理错误,例如 .catch(err => throw err).catch(handleError)
  • 不会在那一秒throw err === return Promise.reject(err).catch() 吗?
  • 是的,那些总是等价的,当你throw 你必须catch,这就是承诺的意义,它反映了同步行为。阅读这篇文章,它会澄清你的疑惑blog.domenic.me/youre-missing-the-point-of-promises
猜你喜欢
  • 2014-02-11
  • 2015-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2020-06-13
  • 1970-01-01
相关资源
最近更新 更多