我们在前面的文章《JavaScript 基础:异步编程/单线程和异步》中讲过,Javascript 是⼀⻔单线程语⾔。早期我们解决异步场景时,⼤部分情况都是通过回调函数来进⾏。
(如果你还不了解单线程和异步的概念,可以先去回顾上一篇文章。)
回调函数的定义
把函数 A 传给另一个函数 B 调用,那么函数 A 就是回调函数。
例如在浏览器中发送 ajax 网络请求,或者在定时器中执行异步任务,就是最常⻅的异步场景。发送请求后,需要等待一段时间,等服务端响应之后我们才能拿到结果。如果我们希望等待异步任务结束之后再执⾏想要的操作,就只能通过回调函数这样的⽅式进⾏处理。
const dynamicFunc = function (callback) {
setTimeout(function () {
console.log("一开始在这里执行异步任务 task1,延迟3秒执行");
// task1: total 计数
let total = 0;
for (let i = 0; i < 10; i++) {
total += i;
}
// 等待异步任务 task1 执行完成后,通过回调传入的 callback() 函数,通知外面的调用者,可以开始做后续任务 task2 了
// 如果有需要的话,可以把 task1 的执行结果 total 传给外面。
callback && callback(total);
}, 3000);
};
// 执行同步任务 task2。需要先等 异步任务 task1做完。
dynamicFunc(function (value) {
console.log("外面监听到,异步任务 task1已经完成了,并且还能拿到 task1的执行结果 value");
console.log("task1的返回值value:" + value);
// task2:将task1的执行结果乘以2
const result = value * 2;
console.log("result:" + result);
});
上⾯的例⼦中,dynamicFunc() 函数里面的 setTimeout()就是⼀个异步函数,在里面执行了一些异步任务,延迟3秒执行。dynamicFunc() 的参数 callback() 就是一个回调函数。这段代码的诉求是:先等待 异步任务 task1 做完,再做 同步任务task2。我们来分析一下。
已知异步任务 task1 需要3秒才能做完。3秒结束后,通知 dynamicFunc 函数的调用者,里面的异步任务 task1 已经做完了,外面可以开始做后续的任务 tas