相关概念
-
同步和异步的概念(相对两个参与者)
-
同步:阻塞的 -
异步:不阻塞的 -
js的执行环境:单线程+事件队列(任务队列)
-
什么样的任务会进入任务队列?
- 定时函数(时间到了)
- Ajax回调函数(后端有数据返回)
- 事件处理函数(特定事件被触发)
-
任务队列中的任务何时执行?
- 主线程空闲
- 任务队列中的任务满足特定的触发条件
`
// 如下的打印是否一定发生在2秒后?不一定
// 当2秒到的时候,此时主线程可能正在忙
setTimeout(() => {
console.log('hello')
}, 2000)
`
-
宏任务和微任务
-
宏任务:进入任务队列的任务
-
微任务:不进入浏览器的任务队列,但是会进入另一个队列(内存中自定义队列)
-
微任务队列是通过js代码实现的一种数据结构(可以理解为类似数组的的结构),该任务队列中任务触发的时机:主线程结束后,宏任务执行之前
-
主线程 ---> 微任务 ---> 宏任务
-
何种代码属于微任务?Promise
-
代码实现
- 回调函数
- Promise
- Async/await
. 异步的结果无法通过返回值获取
<script>
function queryData() {
let ret = null
setTimeout(() => {
let data = {
uname: 'lisi',
age: 12
}
// 这里return的是queryData函数的返回值吗?不是
// 是该回调函数的返回值
// return data
ret = data
}, 2000)
return ret
}
// 需求:2秒后获取函数内部异步的结果数据
let ret = queryData()
console.log(ret)
</script>
- 异步结果需要通过回调函数的方式才可以得到
<script>
function queryData(callback) {
setTimeout(() => {
let data = {
uname: 'lisi',
age: 12
}
// 调用回调函数(2秒后才会调用回调函数)
callback(data)
}, 2000)
}
// 结论:异步的结果必须用回调函数才可以获取到
queryData((ret) => {
console.log(ret)
})
</script>
- 如果有多个异步任务,并且要保证异步任务执行的顺序,需要如何处理?
需求:有3个异步任务a/b/c,分别延时1/2/3秒返回异步的数据,要求得到数据的顺序:c-->a-->b
- 要想实现上述任务,需要进行回调函数的嵌套,如果嵌套层次太多,就会出现回调地狱问题
- 由于回调地狱代码可读性较差,所以就诞生了一种新的技术:Promise
Promise是回调函数一种语法糖,一种改进的写法,但是并没有在本质上发生变化(依然是为了得到异步结果)
- Promise中依然有回调,也不是最好的方案,所以ES7引入了新的方案:async函数