Node之回调函数为什么第一个参数为error

本文采取层层递进的方式,让读者更容易理解

回调函数

在讲解回调函数之前,我们先来看一段代码:

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表示没有异常发生。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值