谈谈js执行机制(异步)?
引言:
+ JS 是「单线程语言」,执行顺序 「自上而下」「逐行执行」(不能同时执行多行js代码)
+「JS可以操作DOM」,所以为了避免DOM渲染冲突,JS和DOM渲染共用同一个线程,即js执行时,DOM渲染会停止
js执行机制?
单线程?
异步和同步?
同步任务和异步任务?
异步应用场景?
异步的解决方案-event loop?
什么是执行栈和任务队列?
关于微任务和宏任务?
回调地狱?
提升-关于Promise?
提升-手写Promise?
提升-async和await和(Promise关系)?
1. js执行机制?
** 执行机制:
1. 先执行「执行栈」中的 「同步任务」
2. 遇到「异步任务」,将「异步任务(回调函数)」放入「任务队列」中
3. 执行完「执行栈」中所有「同步任务」后,将「任务队列」中的「异步任务」放入「执行栈」中,开始执行。
** 遇到多个「异步任务」处理方式:
1. 先执行「执行栈」中的「同步任务」
2. 遇到「异步任务」,“ 将该「异步任务」提交给「异步进程处理」”,再决定是否需要放入「任务队列」
3. 执行完「执行栈」中所有「同步任务」后,将「任务队列」中的「异步任务」放入「执行栈」中,开始执行。
“执行完后,还会看「任务队列」中有没有新的异步任务,有,就会把他放入「执行栈」中继续执行” -------事件循环
2. 单线程?
- 单线程定义: 只有一个线程,同一时间,只能做一件事儿
- 单线程缺点: 效率低, 可能会阻塞后面任务执行
- 解决单线程缺点方案:用「异步」,提高效率
3. 异步?
- 异步定义: 同时做多个「任务」,不会阻塞后面任务执行
- 同步定义: 逐行执行,前一个「任务」结束,后一个任务才能执行,可能会阻塞后面任务执行
- 异步的优缺点:
优点:
1.不会阻塞后面任务的执行
缺点
1. 没有按照书写顺序执行, 可读性差
4. 同步任务和异步任务?
- 同步任务:都在「主线程」上执行,形成「执行栈」
- 异步任务:回调函数,放在「任务队列」中
js异步,是通过「回调函数」执行的
1. 定时器: setTimeout, setInterval
2. 资源加载: load
3. 事件: onclick
5. 异步应用场景?
需要等待的情况需要异步
- a. 网络请求(ajax, 图片加载)
- b. 定时任务(setTimeout, setInterval)
6. 异步的解决方案-event loop?
-
event loop定义:由于「执行栈」中不断获得「异步任务」、执行任务、再获得「异步任务」、再执行,这种机制被称为“事件循环”
-
event loop实现原理:
1. 将「异步任务」先放在「异步队列」中
2. 将「同步任务」执行完毕后
3. 「轮询执行」 查询「任务队列」中是否还有「异步任务」,将他们依次放入「执行栈」中执行
7. 什么是执行栈和任务队列?
- 1.执行栈: 所有「同步任务」都在「主线程」上执行,这个「主线程」就是「执行栈」
- 2.任务队列: 存放「异步任务」(包括微任务和宏任务)的消息队列,
8. 关于微任务和宏任务?
- js 运行机制,执行顺序:同步任务 > 异步任务(微任务 > 宏任务)
- promise特殊: Promise构造函数中函数体的代码立即执行(new Promise())
- async 特殊:在出现await出现之前,其中的代码也是立即执行的。
- 微任务:
1. Promise.then()
2. Promise.catch()
3. Promise.finally()
4. nextTick
5. MutationObserver
- 宏任务:
1. setTimeout
2. setInterval
3. setImmediate
4. I/O 操作
9. Promise?
- 三种状态: Pending、fulfilled、rejected
- 初始状态: Pending
- 状态变化:Pending -> fulfilled, Pending -> rejected
- 注意事项:
1. 状态不可逆
2. Promise必须实现.then()这个方法
3. then 只是将callback 拆分了
4. then() 参数,可以接收两个函数
5. then() 返回的,必是一个Promise实例
- 基本语法(.then())
const pro = new Promise((resolve, reject) => {
resolve()
})
<!--第一个是成功回调,第二个是错误回调 -->
pro.then(() => {
<!--这是成功回调-->
}, () => {
<!--这是错误回调-->
} )
- 异常捕获:统一捕获异常(catch)
<!--捕获程序的语法错误-->
pro.then(()=> {
// 成功回调1
}).then(()=> {
// 成功回调2
}).catch(() => {
// 在这里统一捕获异常
})
// reject 携带参数,那么catch中就可以捕获逻辑错误
- 多个串联(链式执行)
result1 = function () {}
result2 = function() {}
result1.then(params1 => {
return result2
}).then((params2) => {
console.log('-----')
}).catch((err) => {
console.log(err)
})
- Promise.all和Promise.race
1. 接收参数: promise对象的数组
2. Promise.all: 全部执行完后,统一执行success
Promise.all([]).then((datas) => {
// datas是数组
})
3. Promise.race: 多个promise同时执行,只要一个完成,就执行success
Promise.race([]).then((data) => {
// data是单个数据
})
10. async和await?
- async/await: 最直接的同步写法
- 写法注意:
1. 使用await,必须使用async
2. await后面跟的是Promise实例
3. 需要babel-polyfill