应用场景
- 网络请求,如
ajax
,图片加载 - 定时任务,如
setTimeout
Promise解决callback hell
function loadImg(src) {
const p = new Promise(
(resolve, reject) => {
const img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror = () => {
const err = new Error(`图片加载失败 ${src}`)
reject(err)
}
img.src = src
}
)
return p
}
// loadImg(url).then(img => {
// console.log(img.width)
// return img
// }).then(img => {
// console.log(img.height)
// }).catch(ex => console.error(ex))
const url1 = 'https://img.mukewang.com/5a9fc8070001a82402060220-140-140.jpg'
const url2 = 'https://img3.mukewang.com/5a9fc8070001a82402060220-100-100.jpg'
loadImg(url1).then(img1 => {
console.log(img1.width)
return img1 // 普通对象
}).then(img1 => {
console.log(img1.height)
return loadImg(url2) // promise 实例
}).then(img2 => {
console.log(img2.width)
return img2
}).then(img2 => {
console.log(img2.height)
}).catch(ex => console.error(ex))
1. Promise三种状态
pending resolved rejected
pending——> resolved 或 pending——> rejected
变化不可逆
2. Promise状态的表现
pending状态,不会触发then和catch
resolved状态,会触发后续的then回调函数
rejected状态,会触发后续的catch回调函数
3. then和catch改变状态
then正常返回resolved,里面有报错则返回rejected
catch正常返回resolved,里面有报错则返回rejected
场景题 - promise then和catch的连接
event loop(时间循环、事件轮询)
同步代码,一行一行放在 Call Stack执行
遇到异步,会先“记录”,等待时机(定时、网络请求等)
时机到了,就移动到Callback Queue
如 Call Stack 为空(即同步代码执行完)Event Loop开始工作
轮询查找Callback Queue,如有则移动到Call Stack执行
-
然后继续轮询查找(永动机一样)
async/await和Promise的关系
async/await是语法糖,本质还是回调函数
执行async函数,返回的是Promise对象
await相当于Promise的then(await后面的代码相当于执行异步回调)
try...catch可捕获异常,代替了Promise的catch
for - of的 应用场景: 实现异步遍历
宏任务 macroTask 和微任务 microTask
- 宏任务: setTimeout,setInterval,Ajax,DOM事件
- 微任务: Promise async/await
微任务执行时机比宏任务早
1. event-loop和DOM渲染的关系
Call Stack空闲时,就会尝试DOM渲染,然后触发event loop,再执行Callback Queue里的代码,再尝试DOM渲染,如此循环
2. 微任务和宏任务的区别
- 宏任务: DOM渲染后触发,如setTimeout
- 微任务: DOM渲染前触发,如Promise
3. 微任务和宏任务的根本区别
- 宏任务是由浏览器规定的,微任务是由ES6语法规定的
- 执行顺序:
1. 同步代码执行完
2. 执行当前的微任务(微任务不放在Web APIs里,放在micro task queue里)
3. 尝试DOM渲染
4. 触发event loop