WEB程序员笔记

一个前端开发工程师的个人博客

什么是JavaScript中的回调以及如何使用它们

回调是在JavaScript中理解的一个非常重要的主题。在本文中,我们将看到什么是回调以及如何使用它们。

什么是回调

首先,我们将看到一个常规的javascript函数,并从那里将看到如何使用回调。

常规Javascript函数

因此,首先让我们看一下javascript中的正常函数。

function multiply(a, b) {
  var result = a * b;
  console.log("multiply Function Result:",result);
}
multiply(2, 4);

这里我们有一个简单的函数,将两个数字相乘。然后,我们使用输入2和4调用该函数。

回调示例1

现在想象一下在乘法计算结果后是否必须立即运行另一个操作。这是我们使用回调的地方。下面的代码显示了这一点。

function multiply(a, b, callback) {
  var result = a * b;
  console.log("multiply Function Result:",result);
  callback(result);
}

function checkOddEven(result){
    var isEven = result % 2 == 0
    if(isEven){
        console.log('checkOddEven Function:',result,' is Even');
    }
    else
    {
        console.log('checkOddEven Function:',result,' is Odd');
    }
}

multiply(7, 9, checkOddEven);

在乘法函数中,我们接受回调以及输入。

当我们调用乘法函数时,我们将回调传递为checkOddEven。因此,基本上,回调不过是一个函数。checkOddEven是用于检查数字是奇数还是偶数的函数。

最后,在乘法函数中,我们有callback(result)。这是我们要求回调函数执行的地方。

所以在上面的代码中,顺序如下

  • 首先,我们调用乘法函数并传递checkOddEven作为回调
  • 乘法函数执行并计算乘法结果
  • 一旦计算出结果,乘法函数就会要求回调执行。
  • 在这种情况下,回调是checkOddEven函数。因此,checkOddEven函数将执行。

上面代码的结果如下所示

multiply Function Result: 63
checkOddEven Function: 63  is Odd

我们可以将任何函数传递给回调。

回调示例2

让我们看下面的脚本

function multiply(a, b, callback) {
  var result = a * b;
  console.log("multiply Function Result:",result);
  callback(result);
}

function checkPosNeg(result){
    var isPositive = result >= 0; 
    if(isPositive){
        console.log('checkPosNeg Function:',result,' is Positive');
    }
    else
    {
        console.log('checkPosNeg Function:',result,' is Negative');
    }
}
multiply(-7, 9, checkPosNeg);

在这里,我们有一个名为checkPosNeg的函数,该函数检查数字是正数还是负数。

在此示例中,我们将回调作为checkPosNeg传递。

上面程序的输出如下

multiply Function Result: -63
checkPosNeg Function: -63  is Negative

从此示例中,我们看到可以将任何函数传递给callback

匿名回叫功能

传递回调的另一种方法是使用匿名函数。如下所示。

function multiply(a, b, callback) {
  var result = a * b;
  console.log("multiply Function Result:", result);
  callback(result);
}

multiply(-7, 9, function(result) {

  if (result > 0) {
    console.log('checkPosNeg Function:', result, ' is Positive');
  } else {
    console.log('checkPosNeg Function:', result, ' is Negative');
  }
});

在这种情况下,我们看到回调函数是在调用乘法函数的同时创建的。此函数基本上检查数字是正数还是负数,但是该函数没有任何名称。

回调中的错误处理

以下代码段显示了如何在回调中进行错误处理。

function divide(a, b, callback) {
  if (b != 0) {
    var result = a / b;
    console.log('divide Function Result', result);
    callback(null, result);
  } else
    callback(new Error('Divide by 0 Error:' + a + '/' + b))
}

function checkPosNeg(error, result) {
  if (error) {
    console.log('checkPosNeg Function cannot run');
    console.log(error);
  } else {
    var isPositive = result >= 0;
    if (isPositive) {
      console.log('checkPosNeg Function:', result, ' is Positive');
    } else {
      console.log('checkPosNeg Function:', result, ' is Negative');
    }
  }
}

divide(4, 0, checkPosNeg);

在这种情况下,我们有一个函数调用的鸿沟具有回调checkPosNeg

现在,当b为0时,则无法进行除法。如果无法进行除法,则我们无法将任何结果发送到回调。

因此,在这种情况下,我们将回调函数定义为checkPosNeg(error,result)

只要有可能进行除法,我们就调用callback(null,result)表示没有错误,一切都很好。

如果无法进行除法,则我们调用callback(new Error(’Error message’)),它告诉您存在错误。

现在在checkPosNeg函数中,我们还需要检查错误。如果error不为null,那么我们需要在代码中采取必要的措施。例如,这里我们只是打印错误消息。

为什么我们需要回调

您可能会想到的一个明显问题是,为什么我们甚至需要回调。

让我们看下面的代码片段

console.log('Task1');
makeServerCall(url,function(error,result){
    console.log('Task2');
});
console.log('Task3');

在上面的代码中,首先打印Task1

接下来的makeServerCall函数进行网络调用。

现在任务3之前或之后进行打印任务2

通常,每当我们进行网络呼叫时,代码都会继续执行下一条语句,而不会等待结果同步。

因此,在进行网络调用的那一刻,代码将继续执行下一条语句并显示Task3

一旦网络呼叫完成并且响应返回,则将打印Task2

因此,此处makeServerCall回调作为其输入。因此,一旦服务器调用完成,它将执行回调。

在这种情况下,回调使我们能够在网络调用完成后运行某些操作,而不会阻塞代码(即,在网络调用完成之前,不会阻塞将来的语句)。

回调回调

回调可以链接在一起

采取以下代码段。

function1(input1, function(error, result1) {
  function2(result1, function(error, result2) {
    function3(result2, function(error, result3) {
      console.log('Callback Chain')
    })
  })
})
  • 在这里,首先我们等待function1完成网络调用并执行第一个回调。
  • 第一个回调依次调用function2。一旦function2完成其网络调用,它将执行第二个回调。
  • 第二个回调调用function3。一旦function3完成其网络调用,它将执行第三个回调。
  • 第三个回调仅打印一条消息。

也可以将更多的回调链接在一起。

这里似乎没有东西

嗯,就像您在上面的脚本中可能已经注意到的那样,随着回调次数的增加,它变得有点难以理解。

上面的示例仅显示了单行功能。如果函数稍大,链接回调的数量更多,则代码将高度不可读。同样,这意味着调试代码非常非常困难。

这里有一个样本片段来说明这一点

function1(input1, function(error, result1) {
  if (error) {
    console.log('Error')
  } else {
    function2(result1, function(error, result2) {
      if (error) {
        console.log('Error')
      } else {
        function3(result2, function(error, result3) {
          if (error) {
            console.log('Error')
          } else {
            function4(result3, function(error, result4) {
              if (error) {
                console.log('Error')
              }
            })
          }
        })

      }
    })
  }
})

这个问题被称为厄运金字塔

解决此问题的一种方法是使用Promises,我将在以后的文章中介绍

恭喜😄

现在,您知道什么是回调以及如何使用它们。

快乐编码😄

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注