处理 Node.Js 中的异常

Node.js 有 3 种处理异常/错误的基本方法:

  1. try-catch
  2. error 作为 callback 的第一个参数
  3. emit 使用 eventEmitter 的错误事件

try-catch 用于捕获从同步代码执行中抛出的异常。如果调用者(或调用者的调用者,…)使用 try / catch,那么他们可以捕获错误。如果没有任何调用者尝试捕获而不是程序崩溃。
如果在异步操作上使用 try-catch,则异步方法的回调抛出异常,而不会被 try-catch 捕获。要从异步操作回调中捕获异常,最好使用 promises
更好地理解它的例子

// ** Example - 1  **
function doSomeSynchronousOperation(req, res) {
    if(req.body.username === ''){
        throw new Error('User Name cannot be empty');
    }  
    return true;  
}

// calling the method above
try {
    // synchronous code   
    doSomeSynchronousOperation(req, res)    
catch(e) {
    //exception handled here   
    console.log(e.message);  
} 

// ** Example - 2 **
function doSomeAsynchronousOperation(req, res, cb) {
    // imitating async operation
    return setTimeout(function(){
        cb(null, []);
    },1000);
}
 
try {
    // asynchronous code   
    doSomeAsynchronousOperation(req, res, function(err, rs){
        throw new Error("async operation exception");
    })   
} catch(e) {
     // Exception will not get handled here
     console.log(e.message);  
}
// The exception is unhandled and hence will cause application to break

回调主要在 Node.js 中使用,因为回调是异步传递事件的。用户向你传递一个函数(回调),并在异步操作完成后稍后调用它。
通常的模式是回调被调用为回调(错误,结果) ,其中只有一个错误和结果是非空的,这取决于操作是成功还是失败。

function doSomeAsynchronousOperation(req, res, callback) {
   setTimeout(function(){
        return callback(new Error('User Name cannot be empty'));    
   }, 1000);  
   return true;
}

doSomeAsynchronousOperation(req, res, function(err, result) {
   if (err) {
       //exception handled here 
       console.log(err.message);
   }
   
   //do some stuff with valid data
});

发出更复杂的情况,而不是使用回调,函数本身可以返回一个 EventEmitter 对象,并且调用者应该监听发射器上的错误事件。

const EventEmitter = require('events');

function doSomeAsynchronousOperation(req, res) {
    let myEvent = new EventEmitter();

    // runs asynchronously
    setTimeout(function(){
        myEvent.emit('error', new Error('User Name cannot be empty'));
    }, 1000);

    return myEvent;
}

// Invoke the function
let event = doSomeAsynchronousOperation(req, res);

event.on('error', function(err) {
    console.log(err);
});

event.on('done', function(result) {
    console.log(result); // true
});