异步

在 JavaScript 中很多执行不是立刻进行的,比如读取个文件、加载网络URL、DOM操作等等,执行这些不是立刻执行,且稍后才能得到结果的就是 异步执行。与之相对的,立刻执行并能得到结果的就是同步执行

$$tip

你可以发现,异步执行的函数基本都是耗时长的函数,比如读取文件或加载网络 URL。设想一下,如果这些是同步执行,那么将会阻塞我们 JavaScript 进程, 那么之后的代码都得等待执行完成,会造成页面卡死。

$$

常用的 setTimeout 也是典型的异步函数:

console.log("开始执行") // 同步执行
setTimeout(() => console.log("大家好"), 3000) // 异步执行
console.log("结束执行") // 同步执行

// 最终结果
// 开始执行
// 结束执行
// 大家好

回调

使用异步执行就有个问题了,我们不知道执行有没有完成,有没有成功,执行结果也不得而知。

$$jsdemo$$
$$edit$$
function loadFile() {
    // 读取文件需要三秒钟
    setTimeout(function () {
        const file = "文件内容"
        console.log(file)
        return file // 外部无法获取返回的 file
    }, 3000)
}
console.log("开始执行") // 同步执行

const file = loadFile() // 无法得到执行结果
console.log(`文件内容:${file}`) // 文件内容:undefined

console.log("结束执行") // 同步执行

为了解决这个问题,我们想出了一种方法。传递一个函数,使得调用方在函数执行结束时调用,并传递执行结果。这种方式就被称为回调,而执行结束时调用的函数就被称为回调函数。

$$jsdemo$$
$$edit$$
function loadFile(callback) {
    // 读取文件需要三秒钟
    setTimeout(function () {
        const file = "三眼鸭的编程教室"
        // 将结果作为参数传到回调中
        callback(file)
    }, 3000)
}
console.log("开始执行") // 同步执行

loadFile(function (file) {
    // 得到执行结果
    console.log(`文件内容:${file}`) // 文件内容:三眼鸭的编程教室
})

console.log("结束执行") // 同步执行