Node之为什么回调函数第一个参数是err
程序员文章站
2022-03-20 18:25:08
本文采取层层递进的方式,让读者更容易理解回调函数在讲解回调函数之前,我们先来看一段代码:function fn(){ function fn2(){ function fn3(){ console.log(3) } fn3(); console.log(2) } fn2(); console.log(1)}fn();console.log(4)执行结果是什么?很简单 3 2 1 ....
本文采取层层递进的方式,让读者更容易理解
回调函数
在讲解回调函数之前,我们先来看一段代码:
function fn(){
function fn2(){
function fn3(){
console.log(3)
}
fn3();
console.log(2)
}
fn2();
console.log(1)
}
fn();
console.log(4)
执行结果是什么?
很简单 3 2 1 4
因为函数栈结构是这样的:
先执行fn3,fn3弹出栈后执行fn2,fn2执行完弹出栈,然后执行fn,执行完同样地弹出函数栈,最后执行console.log(4),输出3 2 1 4。
现在假设一个场景:
fn3函数内部是有几率会报错的,修改fn3函数代码:
function fn3(){
if(Math.random() < 0.7){
throw new Error('fn3 err')
}else{
console.log(3)
}
}
我们可以用try…catch语句在fn处捕捉异常:
try{
fn();
}catch(err){
console.log(err)
}
这时我们发现,已经可以捕捉到异常了,但是只打印出了4,因为fn3报错,导致异常被try…catch块捕捉,fn3后的程序无法正确执行。
接着我们将报错程序改成异步的,fn3的报错程序改成如下:
setTimeout(()=>{ throw new Error("error"); }, 0)
结果try…catch块无法捕捉异常,因为setTimeOut会放在所有同步代码执行完之后才执行,try…catch块只能捕捉同步异常,无法捕捉异步异常。
所以程序仍然存在两个问题:
1. 无法捕捉异步异常
2. fn3抛同步异常时会导致后续程序无法正常运行
这个时候回调函数就派上用场了,他可以将错误返回给父程序处理,同时不影响后续程序运行,即使在异步条件下,也可以正确执行,实现很简单,即在fn函数传入一个callback参数(名称自定义),让可能出错的程序执行callback函数,如下:
function fn(callback){
function fn2(){
function fn3(){
if(Math.random() < 0.7){
// 场景1: 同步异常
callback(new Error("error1"));
// 场景2: 异步异常
// setTimeout(()=>{
// callback(new Error("error1"));
// }, 0)
}else{
callback(null, 3)
console.log(3)
}
}
fn3();
console.log(2)
}
fn2();
console.log(1)
}
// try{
// fn();
// }catch(err){
// console.log(err)
// }
fn(function(err, res) {
if(err) console.log(err)
else console.log(res)
})
这样子的话,也就解释了为什么当需要抛出异常的时候,error参数永远是放在callback函数的第一位,因为在这里我们设定了new Error放置在callback的第一个参数,那么就约定俗成的让error定义在第一位了。而当没有异常发生的时候,第一位则传入null表示没有异常发生。
本文地址:https://blog.csdn.net/qq_43538596/article/details/111030499