什么是回调函数?
相信很多小伙伴和我一样,在学习JavaScript的时候呢,经常会看到回调函数的出现,可以如果要自己去写或者讲述如何理解回调函数的呢,又不知道从哪谈起。下面我们一起来学习一下什么是回调函数。
在MDN中,是这样解释回调函数的:回调函数都是作为参数传给另一个函数的函数,然后通过在外部函数内部调用该回调函数已完成某种操作
通俗点解释呢,就是函数A作为参数传递到函数B中,并且这个函数B执行函数A,那么函数A就叫作回调函数;如果这个函数没有名称(函数表达式),就叫作匿名回调函数。
何时需要回调函数?
下面我们来看一段代码
function A(){
console.log("起床");
}
function B(){
console.log("刷牙");
}
A();
B();
我们一定知道这两个函数一定会先执行A再执行B
// 起床
// 刷牙
但是我们的“起床”时间被耽误了,无法立即执行,下面我们来模拟一下
function A(){
setTimeout(function(){
console.log("起床");
},500)
}
function B(){
console.log("刷牙");
}
A();
B();
这个时候我们再来看打印台的输出
// 刷牙
// 起床
起床在刷牙之后输出了,可能有人会说,因为你设置了一个定时器,让A函数延迟了500ms输出,才造成了刷牙在前,起床在后。确实如此,但是我们这里写定时器只是模拟API请求(先发送请求然后等待响应),在此之后,我们仍希望它按照顺序执行,否则这这些函数所发生的事件不就乱套了吗。
这个时候我们的回调函数就可以登场了,回调函数可以确保某些代码在其他代码已经完成执行之前不会执行的方法。(B函数不会在A函数指向之前执行)。
创建一个回调函数
还是利用利用上面的代码,我们把他修改成一个回调函数
function B(value){
console.log(`我要${value}了`);
}
function A(othFunc,value1,value2){
console.log(`我要${value1}了`);
othFunc(value2);
}
A(B,"起床","刷牙");
下面来看上面代码打印的结果
// 我要起床了
// 我要刷牙了
我们仍然用定时器模拟API请求,但是输出的结果是一样的,
function B(value){
console.log(`我要${value}了`);
}
function A(othFunc,value1,value2){
setTimeout(function(){
console.log(`我要${value1}了`);
othFunc(value2);
},500)
}
A(B,"起床","刷牙");
// 我要起床了
// 我要刷牙了
匿名回调函数
相信你看了上面的代码,应该也知道回调函数如何使用了,下面我们来看一下匿名回调函数
function add(num1,num2,callback){
var sum = num1+num2;
return callback(sum);
}
let result = add(1,2,function(num){
return num*num;
});
console.log(result);
回调地狱
通过上面的讲解,大家应该也基本了解了回调函数,但是在使用过程中,回调函数可不是随意使用的。有时候,我们为了实现某些逻辑经常会写成层层嵌套的回调函数,如果嵌套过多,会极大的影响代码的可读性和逻辑,这种情也被称之为回调地狱,有时也称为毁灭金字塔。
var sayHello = function (name,callback) {
setTimeout(function () {
console.log(name);
callback();
},1000);
}
sayHello("first",function(){
sayHello("second",function(){
sayHello("third",function(){
console.log("end");
});
});
});
// first second third end
解决回调地狱
解决回调地狱方法有很多方法:比如:Promise 对象、Generator 函数、async 函数。
关于promise大家也可以关注一下,下一篇博客估计就是Promise了