异步
知识点:
-
单线程和异步
js是单线程语言同时只能做一件事
浏览器和node.js已支持js启动进程,如web worker
js和dom渲染共用同一个线程,因为js可修改dom结构
遇到等待网络请求定时任务等不能卡住,所以需要异步
异步借助callback实现,不会阻塞后面代码执行
同步会阻塞代码执行 -
应用场景
网络请求、定时任务 等待的时候cpu是空闲的造成资源浪费所以需要异步。
图片加载,src 改变路径之后才会触发 onload事件
img.onload = function(){
...
}
img.src = ""
- callback hell 和promise
return 一个普通对象或者promise实例都可以,then中都可以接受到。
异步进阶
event loop 事件轮询
event loop 就是异步回调的实现原理
call stack 调用栈
webAPIs 在es规范之外浏览器定义的一些相关接口 如setTimeout dom bom
callback Queue 回调函数队列
同步代码执行完callstack空了 启动event loop 机制
- 同步代码一行一行放在call stack 中执行
- 遇到异步会先记录下,等待时机
- 如果callstack为空,eventLoop开始工作
- 轮询查找callback queue,如有则移动到call stack中执行
- 然后继续轮询查找就像永动机一样!
- 点击事件同理,把click放到webAPIs中存储下来,点击后放到callbackqueue中
- ajax同理,服务器返回时触发。
- dom事件也使用回调,基于eventloop实现,但是dom事件不是异步
- 触发时机是由浏览器来监听控制
promise 进阶
- 三种状态
pending 过程中,不会触发then和catch
resolve 已经解决了,触发then
rejected 失败了 被拒绝,触发catch
变化不可逆 - 状态的变化和表现
then正常返回resolve,里面有报错则返回rejected
catch正常返回resolve,里面有报错则返回rejected - then和catch对状态的影响
async await 和promise的关系
同步语法 彻底消灭回调函数,不使用then
!(async function(){
...await..
})()
使用!作用是隔开前面的代码,避免不加;的情况
- async/await 是消灭异步的终极武器,但和promise不互斥,两者相辅相成
- 执行async函数返回的是一个promise对象
- await相当于promise的then
- try…catch可捕获异常,代替了promise的catch
- 总结 async 封装promise返回promise ,await相当于then
异步的本质
async/await 只是一个语法糖,语法层面解决问题。
await后面无论有多少行都可以看做是callback里的内容即异步
await asyncfunc()//先执行完此步骤在执行下一句
console.log(1)//这句在await后面可以看作异步代码不管有几行! 相当于 Promise.resolve().then(console.log(1))
for of
for in(以及forEach for)是常规的同步遍历
for… of 常用于异步的遍历
function muti(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * num);
}, 1000);
});
}
const num = [1, 3, 5];
// num.forEach(async (element) => {
// const res = await muti(element);
// console.log(res);
// }); 一秒后全部输出
(async () => {
for (let i of num) {
const res = await muti(i);
console.log(res);
}
})(); //一秒后每隔一秒输出
宏任务(macroTask)微任务(microTask)
- 什么是宏任务,什么是微任务
宏任务:setTimeout setInterval ajax dom事件
微任务:Promise async/await
微任务执行时机比宏任务要早 - eventLoop 和dom渲染
- 每次call stack清空(即每次轮询结束),即同步任务执行完毕
- 都是dom重新渲染的机会,dom结构如有改变则重新渲染
- 然后在去触发下一次event loop
- 微任务和宏任务的区别
宏任务:dom渲染后触发,如setTimeout
微任务:dom渲染前触发,如promise
同步代码=》微任务=》dom渲染=》宏任务
为什么?
从eventloop的角度解释,为何微任务执行时机更早
微任务是es6语法规定的,存放在microtask queue中
宏任务是由浏览器规定的,存放在callback queue中