异步与回调

同步与异步的区别
通过【回调】获得异步任务的结果
输出结果的优先级:同步 => 异步 => 回调
参考资料:方应杭:异步与回调

代码执行顺序

同步优先、异步靠边、回调垫底

1
2
3
4
5
console.log(1)
setTimeout(function(){
console.log(2)
},0)
console.log(3)

上面代码的书写顺序是 1 -> 2 -> 3;

但是执行顺序是 1 -> 3 -> 2。

中间的 console.log(2) 就是异步执行的。

你现在知道了「代码的书写顺序和执行顺序居然可以不同!」

同步与异步的区别

同步:你用饿了么点外卖,然后在楼下一直等外卖小哥,直到他把外卖送到
异步:你用饿了么点外卖,然后去玩游戏,过一会外卖小哥打电话说外卖送到楼下了,你再下楼去取外卖。【其中,外卖小哥打电话通知你的这个行为称为“回调”】

同步:一定要等任务执行完了,得到结果,才执行下一个任务。

1
2
3
4
5
6
function taskSync(){
return '同步任务的返回值'
}
var result = taskSync() // 那么 result 就是同步任务的结果
nextTask() // 然后执行下一个任务

异步:不等任务执行完,直接执行下一个任务。

1
2
3
4
5
6
7
8
9
function taskAsync(){
var result = setTimeout(function(){
console.log('异步任务的结果')
}, 3000)
return result
}
var result = taskAsync() // result 不是异步任务的结果,而是一个 timer id
otherTask() // 立即执行其他任务,不等异步任务结束

我们拿到的 result 不是异步执行的结果,而是一个 timer id,那么要怎么拿到异步任务的结果呢?

答案是用【回调】!

回调

将一个函数作为参数传递给另一个函数,作为参数的这个函数就是回调函数。

同步回调

1
2
3
4
5
6
7
8
9
10
11
var callback = function(arg3) {
console.log('cb:' + arg3)
}
function fn(arg1, arg2, cb) {
var Total = arg1 + arg2;
cb(Total);
console.log('fn1:' + Total)
}
fn(2, 2, callback) // 调用fn()函数,并传入2, 2, callback作为参数

上面的代码执行结果为:

1
2
cb:4
fn1:4

不对啊! 回调函数不是应该在主函数的最后执行吗?
上面的例子是一个同步回调函数,函数的执行顺序依然自上而下顺序执行。
那么什么是异步回调呢?

异步回调

在异步回调中,同步 => 异步 => 回调

1
2
3
4
5
6
7
8
9
10
11
12
function f2() {
console.log('f2 finished')
}
function f1(cb) {
setTimeout(cb,1000) //用setTimeout()模拟耗时操作
console.log('f1 finished')
}
f1(f2); //得到的结果是 f1 finished ,f2 finished

「回调」经常用于获取「异步任务」的结果:

1
2
3
4
5
6
7
8
9
10
11
function taskAsync(callback){
var result = setTimeout(function(){
callback('异步任务的结果')
}, 3000)
return result
}
taskAsync(function(result){
console.log(result) // 三秒钟后,这个 callback 函数会被执行
})
otherTask() // 立即执行其他任务,不等异步任务结束

回调函数的参数

  • 将回调函数的参数作为与回调函数同等级的参数进行传递

  • 回调函数的参数在调用回调函数内部创建

-------------本文结束感谢您的阅读-------------