event Loop
<template> <div></div> </template> <script setup lang='ts'> // setTimeout是宏任务,promise是微任务,宏任务和微任务都是队列数据结构,为先进先出 // 事件循环的机制:同步代码先执行,然后处理微任务队列,接着是宏任务队列中的任务。每次执行一个宏任务后,会再次检查微任务队列,直到清空为止 // 注释为代码执行顺序 async function prom() { // 1.此时只是定义未调用 console.log('Y'); // 9.执行输出Y await Promise.resolve() // 10.await 后面的代码会包装进微任务里面,微任务队列添加该微任务 console.log('x'); // 16.执行第五个微任务,输出x // 遇到连续的await时,需要注意的是,第一个await会把之后的所有代码都包装进微任务 // 1.因此此时的顺序应该是把第一个await添加至微任务队列中 // 2.当执行该微任务的时候执行顺序是输出x,然后把第二个await添加至微任务队列最后面,所以如果中间还有微任务是不会立即执行第二个await await Promise.resolve() console.log('z') } setTimeout(() => { // 2.宏任务队列添加该宏任务 console.log(1); // 17.微任务队列清空,此时执行第一个宏任务,执行该行代码,输出1 Promise.resolve().then(()=>{ // 18.遇到微任务,微任务队列添加该微任务 console.log(2); // 20.执行该微任务,输出2 }) }) // 19.宏任务执行完,检查微任务队列,发现微任务队列有任务,执行微任务,直至清空微任务 setTimeout(() => { // 3.宏任务队列添加该宏任务 console.log(3); // 21.微任务队列已清空,执行第二个宏任务,输出3 Promise.resolve().then(()=>{ // 22.遇到微任务,微任务队列添加该微任务 console.log(4); // 24.执行该微任务,输出4 }) }) // 23.宏任务执行完,检查微任务队列,发现微任务队列有任务,执行微任务,直至清空微任务 Promise.resolve().then(()=>{ // 4. 微任务队列添加该微任务 console.log(5); // 12.此时同步代码已经全部执行完,按照队列顺序执行第一个微任务,输出5 }) Promise.resolve().then(()=>{ // 5. 微任务队列添加该微任务 console.log(6); // 13.执行第二个微任务,输出6 }) Promise.resolve().then(()=>{ // 6. 微任务队列添加该微任务 console.log(7); // 14.执行第三个微任务,输出7 }) Promise.resolve().then(()=>{ // 7.微任务队列添加该微任务 console.log(8); // 15.执行第四个微任务,输出8 }) prom() // 8.执行prom函数 console.log(0); // 11.执行输出0 </script> <style scoped lang='scss'> </style>
第二题
const promise = new Promise((resolve, reject) => { console.log(1); console.log(2); }); promise.then(() => { console.log(3); }); console.log(4);
同步代码执行:
new Promise
构造函数中的代码是同步执行的,因此会依次输出 1
和 2
。
promise.then(...)
中的回调函数是异步的,会被放入微任务队列,等待同步代码执行完毕后再执行。
继续执行同步代码,输出 4
。
微任务队列处理:
同步代码执行完毕后,开始处理微任务队列。
由于 Promise
的状态没有被改变(既没有调用 resolve
也没有调用 reject
),promise.then(...)
中的回调函数不会执行。
因此,3
不会被输出。
第三题:
const promise = new Promise((resolve, reject) => { resolve('success1'); reject('error'); resolve('success2'); }); promise.then((res) => { console.log('then:', res); }).catch((err) => { console.log('catch:', err); })
then:success1
这个题目考察的就是Promise的状态在发生变化之后,就不会再发生变化。开始状态由pending
变为resolve
,说明已经变为已完成状态,下面的两个状态的就不会再执行,同时下面的catch也不会捕获到错误。
第四题
Promise.resolve(1) .then(2) .then(Promise.resolve(3)) .then(console.log)
-
Promise.resolve(1)
-
创建一个状态为
fulfilled
的Promise
,其值为1
。
-
-
.then(2)
-
.then
和catch方法的参数必须是一个函数,但这里传入的是2
(非函数)。 -
根据规范,如果
.then
的参数不是函数,Promise
会直接跳过该.then
,并将上一个Promise
的值传递给下一个.then
。 -
因此,
1
会直接传递到下一个.then
。
-
-
.then(Promise.resolve(3))
-
这里传入的是
Promise.resolve(3)
,它是一个Promise
对象,而不是函数。 -
同样,根据规范,如果
.then
的参数不是函数,Promise
会跳过该.then
,并将上一个Promise
的值传递给下一个.then
。 -
因此,
1
会继续传递到下一个.then
。
-
-
.then(console.log)
-
这里传入的是
console.log
,它是一个函数。 -
上一个
Promise
的值是1
,因此console.log
会输出1
。
-
关键点
-
.then
的参数必须是函数-
如果传入的不是函数(如
2
或Promise.resolve(3)
),Promise
会忽略该.then
,并将上一个Promise
的值直接传递下去。
-
-
Promise.resolve
的作用-
Promise.resolve(1)
创建一个状态为fulfilled
的Promise
,其值为1
。 -
Promise.resolve(3)
创建一个状态为fulfilled
的Promise
,但在这里它被忽略,因为它不是函数。
-
-
值传递
-
由于中间的
.then
被忽略,1
会一直传递到最后的.then(console.log)
,因此输出1
。
-
Promise.resolve(1) .then(res => { console.log(res); return 2; }) .catch(err => { return 3; }) .then(res => { console.log(res); });
Promise是可以链式调用的,由于每次调用 .then
或者 .catch
都会返回一个新的 promise,从而实现了链式调用, 它并不像一般任务的链式调用一样return this。
上面的输出结果之所以依次打印出1和2,是因为resolve(1)
之后走的是第一个then方法,并没有进catch里,所以第二个then中的res得到的实际上是第一个then的返回值。并且return 2会被包装成resolve(2)
,被最后的then打印输出2。
第六题
Promise.reject('err!!!') .then((res) => { console.log('success', res) }, (err) => { console.log('error', err) }).catch(err => { console.log('catch', err) })
我们知道,.then
函数中的两个参数:
- 第一个参数是用来处理Promise成功的函数
- 第二个则是处理失败的函数
也就是说Promise.resolve('1')
的值会进入成功的函数,Promise.reject('2')
的值会进入失败的函数。
在这道题中,错误直接被then
的第二个参数捕获了,所以就不会被catch
捕获了,输出结果为:error err!!!'
第7题
Promise.resolve('1') .finally(() => { console.log('finally1') throw new Error('我是finally中抛出的异常') }) .then(res => { console.log('finally后面的then函数', res) }) .catch(err => { console.log('捕获错误', err) })
'finally1'
'捕获错误' Error: 我是finally中抛出的异常
.then和.finally都是微任务,按照顺序执行了finally抛出了Error,就会被catch捕获,如果没有抛除异常则正常进入.then函数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现