当前位置: 首页 > 知识库问答 >
问题:

javascript - 两个promise问题?

陆光济
2024-09-26

第一个问题,这个为什么先输出3后输出2呢

      async function p2() {
        return Promise.resolve('p2');
      }

      async function p3() {
        return await Promise.resolve('p3');
      }

      p2().then((res) => console.log(res));
      p3().then((res) => console.log(res));

第二个问题,这个为什么会交错输出呢,142536

new Promise((r) => {
    r();
})
.then(() => console.log(1))
.then(() => console.log(2))
.then(() => console.log(3))

new Promise((r) => {
    r();
})
.then(() => console.log(4))
.then(() => console.log(5))
.then(() => console.log(6))

promise小白一枚,上述两个疑问,希望能得到详细的解答

共有3个答案

丁灿
2024-09-26

第一个问题:

  1. async function执行返回promise,p2和p3执行后先后注册微任务
  2. 同步代码执行完轮到p2的回调执行,return Promise.resolve('p2')又将一个微任务入队了
  3. p3的回调执行,await强制了后续的执行
  4. 由于p3()返回的promise的状态变为了fulfilled,then()的回调就执行打印了'p3'
  5. 接下来就是剩下的微任务执行,然后then()的回调执行打印了'p2'

第二个问题:
你需要理解Promise/A+规范中对then的定义就是:
链式调用时,后一个then只会在前一个then返回的promise处理完状态变更为fulfilled才会执行(不完全是这样但是等效)

詹钊
2024-09-26

两个问题原因是一样的,.then 和 Promise.resolve 返回的都是 Promise,可以认为是在执行后才会产生一个新的微任务,排队后才能触发之后的流程。

以第一个问题举例,可以理解流程是这样的:

  1. p2 函数调用进入队列
  2. p3 函数调用进入队列
  3. p2 函数执行,返回 Promise.resolve('p2') 进入队列
  4. p3 函数执行,返回 (await Promise.resolve('p3') 也就是 'p3') 进入队列,p3().then 可以被执行了
  5. Promise.resolve('p2') 执行,返回结果 'p2', p2().then 可以被执行了
  6. 【所以按照顺序】p3 先触发、p2 再触发

第二个问题也是类似的,执行完输出 1 的 then callback 之后下一个 then 对应的触发才会进入队列,所以两个 Promise 交错触发。

鞠乐
2024-09-26

第一个问题解答

为什么这段代码先输出 "3" 后输出 "2"?

async function p2() {
    return Promise.resolve('p2');
}

async function p3() {
    return await Promise.resolve('p3');
}

p2().then((res) => console.log(res));
p3().then((res) => console.log(res));

解释

  1. p2 函数:这个函数通过 return Promise.resolve('p2'); 直接返回了一个已解决的 Promise。注意这里并没有使用 await,所以函数执行到 return 时就会立即返回一个 Promise 对象,而不会等待 Promise 解决。
  2. p3 函数:这个函数通过 return await Promise.resolve('p3'); 返回了一个 Promise。由于使用了 await,函数会等待 Promise.resolve('p3') 解决后再继续执行并返回结果。尽管 Promise.resolve('p3') 几乎立即解决,但使用 await 会使得 p3() 函数的执行暂停,直到 Promise 解决。
  3. 执行顺序:由于 p2() 立即返回一个 Promise 并继续执行 .then() 链,而 p3() 等待其内部的 Promise 解决后再继续,因此 p2().then() 链会先被添加到微任务队列中。当当前执行栈清空后(即同步代码执行完毕后),JavaScript 引擎会处理微任务队列中的任务,因此 p2().then() 中的 console.log(res) 会先执行,输出 "2"。随后,p3() 中的 Promise 解决,p3().then() 中的 console.log(res) 才会执行,输出 "3"。

第二个问题解答

为什么这段代码交错输出 "142536"?

new Promise((r) => {
    r();
})
.then(() => console.log(1))
.then(() => console.log(2))
.then(() => console.log(3))

new Promise((r) => {
    r();
})
.then(() => console.log(4))
.then(() => console.log(5))
.then(() => console.log(6))

解释

  1. Promise 链的执行:两个 Promise 链几乎是同时被创建的,并且它们各自内部的 Promise 都是立即解决的(通过 r();)。但是,每个 .then() 方法调用都会将一个新的回调函数添加到各自的 Promise 解决后的微任务队列中。
  2. 微任务队列:JavaScript 有一个微任务队列,用于存放需要在当前执行栈清空后立即执行的异步操作(如 Promise 的解决回调)。由于这两个 Promise 链都是立即解决的,它们的 .then() 回调会被依次添加到微任务队列中。
  3. 执行顺序:当同步代码执行完毕后,JavaScript 引擎会检查微任务队列,并按顺序执行队列中的任务。因此,第一个 Promise 链的 .then() 回调(输出 "1"、"2"、"3")会按照它们被添加到队列中的顺序依次执行,随后是第二个 Promise 链的 .then() 回调(输出 "4"、"5"、"6")。这就导致了交错输出 "142536"。

总结:尽管这两个 Promise 链在代码中看起来是连续书写的,但它们各自的 .then() 回调会根据它们被添加到微任务队列的顺序来执行,而不是根据它们在代码中的位置。

 类似资料:
  • 请问上面这段代码,我想封装成Promise 这种 直接调用this.home_barlist1().then 该怎么改呢? 我改成下面这样 好像不行

  • 我有一个vue写的标签 其中,queryByPrimaryKey返回的是一个promise,所以这里用await等待promise的值,因为用到了await,所以外层又需要用async包裹,这样整体函数返回的又是一个promise,那么src属性实际上要的是返回的string值,而不是包裹着string的promise,我如何拿到string值?

  • 请大佬帮忙分析一下,以下代码执行顺序(正确的顺序是:a 1 2 3 b 4 c 5):

  • 打印2的位置 怎么解释呢

  • 问题内容: 我是一个node.js新手,我试图了解如何以非阻塞方式像节点一样组织一些逻辑。 我有一组环境[‘stage’,’prod’],还有另一组称为品牌[‘A’,’B’,’C’]的参数和一组设备[‘phone’,’tablet’] 。 在节点的回调驱动的世界中,我有这个: 我正在尝试为每个环境构建带有块的报告: 我的问题是,由于这里的所有内容都是如此异步的,尤其是在getTape内部,它调用了

  • Demo 从日志输出来看 先执行了p1后执行p2, 问题 1.Promise.all的参数接受一个Promise数组, Promise数组中每一个Promise的执行函数的 开始执行顺序是怎样的? 是按照数组中的顺序 开始执行每一个Promise的执行函数吗?从实际日志输出来看 好像是数组的倒序 (注意问题问题的是Promise的执行函数的 开始执行顺序,并不是Promise的完成顺序,仅仅是执行