Node.js 最佳实践异常处理——在 Async/Await 之后

Posted

技术标签:

【中文标题】Node.js 最佳实践异常处理——在 Async/Await 之后【英文标题】:Node.js Best Practice Exception Handling - After Async/Await 【发布时间】:2017-01-31 23:25:02 【问题描述】:

他们已经是关于这个话题的问题了

Node.js Best Practice Exception Handling

这是旧的,答案非常过时,domains 从那时起甚至已弃用。

现在在后 Async/Await Node.js 场景中,我们不应该类似地考虑同步和异步情况,并在同步函数中抛出异常并在异步函数中拒绝承诺,而不是在前一种情况下返回 Error 实例。

let divideSync = function(x,y) 
    // if error condition?
    if ( y === 0 ) 
        // "throw" the error 
        throw new Error("Can't divide by zero exception")
    
    else 
        // no error occured, continue on
        return x/y
    

模拟异步除法操作

let divideAsync = function(x, y) 

  return new Promise(function(resolve, reject) 

    setTimeout(function() 
      // if error condition?
      if (y === 0) 
        // "throw" the error safely by rejecting the promise
        reject (new Error("Can't divide by zero exception"));
       else 
        // no error occured, continue on
        resolve(x / y)
      
    , 1000);
  )

;

所以同步和异步异常可以统一处理

let main = async function () 
    try 
        //const resultSync = divideSync(4,0);
        const resultAsync = await divideAsync(4,0);
    
    catch(ex) 
        console.log(ex.message);
    


【问题讨论】:

【参考方案1】:

Node.js Best Practice Exception Handling 的答案已经过时且非常过时

没那么多。 This answer 以及来自 this well-maintained blog post 的列表是最新的。The offical node.js guide 总是一本好书,而且一般方法没有太大变化。

那么发生了什么变化?

域已损坏并已弃用。好吧,那是旧闻了。 不应再使用带有错误优先参数的典型“节点式回调”,它们只触发一次。这种简单的顺序异步编码风格及其所有问题已被 Promise 和 async/await 取代。 (注意:事件发射器等是不同的情况process.on('uncaughtException') 辅以process.on('unhandledRejection') promises 还可以捕获程序员错误如果使用正确。对于无聊的顺序异步代码,它们可以替换域。

那么这对公共代码意味着什么?

难道我们不应该类似地考虑同步和异步情况并在同步函数中抛出异常并在异步函数中拒绝承诺而不是返回Error 实例吗?

是的,没错。你应该用Errors(或throwasync functions)拒绝你的承诺。

请注意,您很少需要亲自致电reject。有了 Promise,您应该可以在代码中使用 throw。如果你不能,你很可能没有正确使用它们——而且程序员的错误也不会在那里被发现。

此代码的黄金法则是:切勿使用非承诺回调的回调。 “Promise 回调”指的是 new Promisethencatch 参数,可能还有一些您的库的自定义方法(例如 finally)。这是您上面的示例代码有问题的地方。写对了,应该是这样的

async function divideAsync(x, y) 
    await new Promise(resolve =>
        setTimeout(resolve, 1000) // don't even pass a function expression
    );
    if (y === 0) 
        throw new Error("Can't divide by zero exception");
     else 
        return x / y;
    

【讨论】:

所以作为一个规则,如果一个异步函数使用 async 则抛出错误,如果没有则拒绝错误 不,即使一个函数不使用 async 语法,但使用了 Promise,您也可以并且应该从 Promise 回调中使用 throw(或 return Promise.reject(…)),例如 @987654345 @ 如果我在我的代码版本中抛出错误,为什么没有捕获(未处理)异常 因为你在抛出一个setTimeout 回调,而不是一个承诺回调。另见here

以上是关于Node.js 最佳实践异常处理——在 Async/Await 之后的主要内容,如果未能解决你的问题,请参考以下文章

52合1Node.js 最佳实践大合集

19 条 Node.js 生产环境中的最佳实践

这是编写以在javascript / node js中处理错误处理then-catch或try-catch的最佳实践[重复]

Spring Async 最佳实践:ExceptionHandler

Ajax+Node.js前后端交互最佳入门实践(03)

最佳实践 beanstalkd (queue) 和 node.js