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是一个检查数字是奇数还是偶数的函数。
在乘法函数的最后,我们有回调函数(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
从这个例子中,我们看到任何函数都可以传递给回调。
匿名回调函数
传递回调的另一种方法是使用匿名函数。其代码如下所示。
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);
在这种情况下,我们有一个名为divide的函数,它有一个回调checkPosNeg。
现在,当 b 为 0 时,除法就无法进行。如果除法无法进行,我们就无法向回调发送任何结果。
因此在这种情况下我们将回调函数定义为checkPosNeg(error,result)。
每当可以进行除法时,我们都会调用回调(null,result)来表示没有错误并且一切正常。
如果无法进行除法,则我们调用回调(new Error('Error message'))来告知出现错误。
现在,在checkPosNeg函数中,我们还需要检查错误。如果错误不为空,则需要在代码中采取必要的措施。例如,这里我们只是打印错误消息。
为什么我们需要回调
您可能会问一个显而易见的问题:我们为什么需要回调?
我们来看下面的代码片段
console.log('Task1');
makeServerCall(url,function(error,result){
console.log('Task2');
});
console.log('Task3');
在上面的代码中,首先打印Task1 。
接下来makeServerCall函数进行网络调用。
现在Task3会在Task2之前还是之后打印?
通常,每当我们进行网络调用时,代码都会继续执行下一个语句,而不会等待同步的结果。
因此,在进行网络调用时,代码将继续执行下一个语句并打印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,我将在以后的文章中介绍
恭喜😄
现在您知道了什么是回调以及如何使用它们。
祝你编码愉快😄
这篇文章最初发表于adityasridhar.com