7

为什么要处理异常?

1.不处理直接导致程序奔溃,这显然不是我们想要的

2.导致请求无法被释放,直至连接超时。用户体验体验非常差,我们要做的应该是在出错时,给用户一个友好的提示,并记录下此次异常,以便排查。

Node.js中常用的异常处理方式

// 每秒钟打印一次时间,确保程序没有奔溃
(function loop() {
    console.log(new Date().getTime())
    setTimeout(function () {
        loop() 
    }, 1000)
})()
// 模拟同步代码块内出现异常
let syncError = () => {
    throw new Error('Sync Error')
}
// 模拟异步代码块内出现异常
let asyncError = () => {
    setTimeout(function () {
        throw new Error('Async Error')
    }, 100)
}

1、try catch 方式

try {
    syncError()
} catch (e) {
    /*处理异常*/
    console.log(e.message)
}
console.log('异常被捕获了,我可以继续执行')

但是try catch方式无法处理异步代码块内出现的异常,你可以理解为执行catch时,异常还没有发生。

try {
    asyncError()
} catch (e) {
    /*异常无法被捕获,导致进程退出*/
    console.log(e.message)
}

clipboard.png

2、callback方式

fs.mkdir('/dir', function (e) {
    if (e) {
        /*处理异常*/
        console.log(e.message)
    } else {
        console.log('创建目录成功')
    }
})

3、event 方式

let events = require("events");
//创建一个事件监听对象
let emitter = new events.EventEmitter();
//监听error事件
emitter.addListener("error", function (e) {
    /*处理异常*/
    console.log(e.message)
});
//触发error事件
emitter.emit("error", new Error('出错啦'));

4、Promise 方式

new Promise((resolve, reject) => {
    syncError()
    /* or
    try{
        syncError()
    }catch(e){
        reject(e)
    }
    */
})
    .then(() => {
        //...
    })
    .catch((e) => {
        /*处理异常*/
        console.log(e.message)
    })

Promise同样无法处理异步代码块中抛出的异常

new Promise((resolve, reject) => {
    asyncError()
})
    .then(() => {
        //...
    })
    .catch((e) => {
        /*异常无法被捕获,导致进程退出*/
        console.log(e.message)
    })

clipboard.png

5、Async/Await 方式

Async/Await是基于Promise的,所以Promise无法捕获的异常,Async/Await同样无法捕获

var sleep = function (time) {
    return new Promise(function (resolve, reject) {
        syncError()
    })
};

(async function () {
    try {
        await sleep(100);
    } catch (e) {
        /*处理异常*/
        console.log(e.message)
    }
})()

6、process方式

process方式可以捕获任何异常(不管是同步代码块中的异常还是异步代码块中的异常)

process.on('uncaughtException', function (e) {
    /*处理异常*/
    console.log(e.message)
});
asyncError()
syncError()

7、domain方式

process方式虽然可以捕获任何类型的异常,但是process太过笨重,除了记录下错误信息,其他地方不适合使用,domain这个也可以处理任何类型异常的模块,显然是一个不错的选择。

let domain = require('domain')
let d = domain.create()
d.on('error', function (e) {
    /*处理异常*/
    console.log(e.message)
})
d.run(asyncError)
d.run(syncError)

YAOHAO
36 声望1 粉丝