1、什么是异步?什么是同步?
- 如果能直接拿到结果,就是同步
- 比如去医院挂号,只有在拿到号码以后,才会离开
- 不拿到结果是不会离开的
- 如果不能直接拿到结果,就是异步
- 比如去网红餐厅吃饭,取了号后可以去继续逛其他的商店,等轮到自己的号码再来吃饭
- 每隔几分钟去问一下服务员现在到第几桌了(轮询)
- 通过小程序、公众号查看当前还有几桌,接受通知(回调)
2、异步举例
- 以 AJAX 为例
request.send()以后,并不能直接得到 response- 需要等待直到 readyState 变为4后,浏览器来回头调用
request.onreadystatechange函数 - 这个过程就像是,你在逛街的时候,餐厅发短信提醒你轮到你就餐了
3、什么是回调
- 写给自己用的函数,不是回调
- 写给别人用的函数,就是回调
- 就像 AJAX 中的
request.onreadystatechange函数,就是用于浏览器来调用的 - 意思就是让浏览器在之后某个时刻来调用以下这个函数
4、回调举例
- 把函数 1 给另一个函数 2
function f1(){}
function f2(fn){
fn()
}
f2(f1)
- f1 是写给 f2 调用的函数,所以 f1 就是回调
5、异步和回调的关系
- 关联:
- 异步任务需要在得到结果时,通知 JS 来获取结果(就像在逛街时,需要有 app 来提醒自己还有多久排到自己)
- 可以让 JS 留一个函数地址(类似于电话)给浏览器
- 异步任务完成时,浏览器调用回调函数的地址即可(打电话通知)
- 同时把结果作为参数传给该回调函数(通知可以来吃饭了)
- 这个函数是通过浏览器调用的,是回调函数
- 区别:
- 异步任务需要用到回调函数来通知结果(或者轮询)
- 但回调函数不一定只用于异步任务里
- 回调也可以用在同步任务里
- 如
array.forEach(n => console.log(n))就是同步回调
6、如何知道一个函数是同步还是异步?
-
如果一个函数的返回值处于
- setTimeout
- AJAX(即 XMLHttpRequest)
- AddEventListener
-
这三个东西内部,那么这个函数就是异步函数
-
例:摇骰子
function 摇骰子(){
setTimeout(()=>{
return parseInt(Math.random()*6)+1
},1000)
}
-
分析:
- 摇骰子() 没有写return,那就是 return undefined
- 箭头函数里有 return ,返回真正的结果
- 所以这是一个异步函数/异步任务
-
例:摇骰子2
const n = 摇骰子()
console.log(n) // undefined
- 那么怎么才能拿到异步函数的结果?
- 答:可以使用回调。写一个函数,然后把函数地址给 摇骰子()
function f1(x){
console.log(x)
}
摇骰子(f1)
- 然后要求 摇骰子函数 得到结果后,把结果作为参数(parseInt(Math.random()*6)+1)传给 f1
function 摇骰子(fn){
setTimeout(()=>{
fn(parseInt(Math.random()*6)+1)
},1000)
}
- 简化
摇骰子(x=>{
console.log(x)
})
- 继续简化
摇骰子(console.log)
//如果参数个数不一致就不能使用这样的简化
7、相关面试题:
- Why?
- Because:
- How
8、总结
- 异步任务是不能拿到结果的
- 于是需要传一个回调给异步任务
- 异步任务完成时,调用回调
- 调用的时候把结果作为参数