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)
  1. Promise.resolve(1)

    • 创建一个状态为 fulfilled 的 Promise,其值为 1

  2. .then(2)

    • .then 和catch方法的参数必须是一个函数,但这里传入的是 2(非函数)。

    • 根据规范,如果 .then 的参数不是函数,Promise 会直接跳过该 .then,并将上一个 Promise 的值传递给下一个 .then

    • 因此,1 会直接传递到下一个 .then

  3. .then(Promise.resolve(3))

    • 这里传入的是 Promise.resolve(3),它是一个 Promise 对象,而不是函数。

    • 同样,根据规范,如果 .then 的参数不是函数,Promise 会跳过该 .then,并将上一个 Promise 的值传递给下一个 .then

    • 因此,1 会继续传递到下一个 .then

  4. .then(console.log)

    • 这里传入的是 console.log,它是一个函数。

    • 上一个 Promise 的值是 1,因此 console.log 会输出 1


关键点

  1. .then 的参数必须是函数

    • 如果传入的不是函数(如 2 或 Promise.resolve(3)),Promise 会忽略该 .then,并将上一个 Promise 的值直接传递下去。

  2. Promise.resolve 的作用

    • Promise.resolve(1) 创建一个状态为 fulfilled 的 Promise,其值为 1

    • Promise.resolve(3) 创建一个状态为 fulfilled 的 Promise,但在这里它被忽略,因为它不是函数。

  3. 值传递

    • 由于中间的 .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函数

posted on   ChoZ  阅读(4)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示