在承诺

时间:2015-06-12 16:15:26

标签: javascript exception promise

我有一个奇怪的情况,我想知道如何解决。 在我的应用程序中,在使用promises的函数之后发生的错误会被抛出,并且app会停止。

这里有一个例子:

getTenant = (req) ->
  deferred = Q.defer()

  deferred.resolve('foo') if req.info.referrer
  deferred.resolve('bar') if !req.info.referrer

  deferred.promise

Routes =[
  {
    method: 'GET'
    path:   '/'
    handler: (request, reply) ->
      getTenant(request).then (tenant) ->
        console.log 'tenant', tenant

        # here `User` is not defined and doesn't even exist
        # why is there no error here?

        if !User.isAuthorized(request, tenant)
          reply 'not authorized'
        else
          reply 'authorized' 

  }
]
getTenant之后{p} User调用一个函数 User不存在或导入,但应用程序没有给我任何错误 那是为什么? 当然,如果我将代码包装在try/catch中,我会抓住错误,但这不是重点。我希望代码实际上会破坏并抛出错误。

这里是完整的示例应用:https://github.com/aschmid/hapierrortest

谢谢你, 安德烈亚斯

2 个答案:

答案 0 :(得分:1)

简短的回答是因为您忽略了包含错误处理程序。 Promise总是需要成功和错误处理功能。

这是承诺的基本(通常是好的)方面。在promise处理程序内(成功或错误),任何抛出的错误都不会触及窗口。相反,promise实现在内部包装try块中的promise处理程序,并且在捕获时,拒绝.then 返回的promise。为什么?这样您就可以选择何时何地以及如何处理错误。这就是为什么你可以在一个长的保证链的末尾放一个catch(errHandler)(这是.then(null, errHandler)的糖):

somePromise.then(function s1 (val1){
  // use val1, return something (e.g. a new promise)
}).then(function s2 (val2){
  // use val2, return something (e.g. a new promise)
}).then(function s3 (val3){
  // use val3, return something (e.g. a new promise)
}).catch(function e1 (err1){
  // handle e1 as you like (console.log, render something on the UI, etc.)
});

在上述链中,somePromises1s2s3发生的错误将在e1处理。这非常好,比在链的每一步都明确处理潜在错误更好。如果你愿意,你仍然可以在每一步处理错误,但它根本不需要。

一般情况下,如果您承诺以某种方式处理错误,那么您根本不想让错误导致应用崩溃。但是如果由于某种原因你想要将错误重新抛出到外部范围,那么你必须使用一个允许重新抛出的最终方法的promise库。例如,Q库中的.done()

答案 1 :(得分:-1)

我首先要说我从未使用过Hapi,但你的语法看起来很好......除了...

如果req.info为空,则会引发异常。试试这个

deferred.resolve('foo') if req.info && req.info.referrer
deferred.resolve('bar') if !req.info || !req.info.referrer