JavaScript - sync + asyns 代码执行顺序 - 我想了解为什么日志以该顺序显示 [关闭]

问题描述 投票:0回答:2

这是我试图理解的一段 Vanilla TS 代码:

console.log("-------------------------- (LOG 1)");

setTimeout(() => console.log("-----------------------------(LOG 2)"), 1000);

const fetchedData = fetch("https://pokeapi.co/api/v2/pokemon/ditto");

const fnReturningNewPromise = () => {
  return new Promise<string>((resolve, reject) => {
    if (1 == 1) {
      console.log("LOG 3 - new Promise in return Statement");
      resolve("fnReturningNewPromise - resolved");
    }

    reject("fnReturningNewPromise - rejected");
  });
};

const customPromise = new Promise<string>((resolve, reject) => {
  if (1 === 1) {
    console.log("LOG 4 - new Promise");
    resolve("Promise resolved");
  } else {
    reject("REJECTED");
  }
});

fetchedData
  .then((res) => {
    console.log("LOG 5 - fetchedData 1st then - res.json()");
    return res.json();
  })
  .then((data) => console.log("LOG 6 - with fetching"));

Promise.resolve(1).then((res) =>
  console.log("LOG 7 - immidielty resolved", res)
);

customPromise
  .then((response) => response)
  .then((data) => console.log("LOG 8 - without fetching"));

console.log("LOG 9 - sync code");

setTimeout(() => {
  console.log("LOG 10 - setTimeout - immidietly resolved");
}, 0);

fnReturningNewPromise().then((res) =>
  console.log("LOG 11 - resolving promise returned from fn: ", res)
);

这是控制台的输出:


-------------------------- (LOG 1) 
LOG 4 - new Promise 
LOG 9 - sync code 
LOG 3 - new Promise in return Statement 
LOG 7 - immidielty resolved 1
LOG 11 - resolving promise returned from fn:  fnReturningNewPromise - resolved 
LOG 8 - without fetching 
LOG 10 - setTimeout - immidietly resolved 
LOG 5 - fetchedData 1st then - res.json() 
LOG 6 - with fetching 
-----------------------------(LOG 2)

console screenshot

我试图找出这些日志的顺序来自哪里。这是我的问题:

  1. 为什么LOG 4显示在LOG 9之前 - LOG 9是纯同步码
  2. 根据上面-为什么LOG 3没有显示在LOG 4之前-它们之间的唯一区别是LOG 3在函数的返回语句中
  3. 为什么LOG 7,LOG 11和LOG 8 - 我可以想象LOG 7是第一个,因为它是immidietly解决的,但为什么LOG 8在LOG 11之前显示? (特别是在代码的第一部分,LOG 4(与 LOG 8 相关)显示在 LOG 3(与 LOG 11 相关)之前
  4. 为什么LOG 10不是最后? - 这是进入任务队列的 setTimeout - 我认为它应该在终点线(LOG 2)之前输出,因为所有其他都是承诺相关的日志(具有更高的优先级)

我很困惑-谁能给我解释一下吗?

我试着在console.log中输出结果,但是最后的效果更让我困惑

javascript asynchronous promise es6-promise executioncontext
2个回答
0
投票

Promise 执行器函数同步执行。

所以通过代码寻找同步执行的代码,日志是

  • “------------------------(日志 1)”

  • custom promise

    的执行者的“log 4 - new Promise”
  • 来自内联代码的“日志 9 - 同步代码”

  • “LOG 3 - new Promise in return Statement”,来自同步调用函数中的 promise 执行器(“in return statement”不是准确描述)。

承诺作业队列中的作业在来自计时器任务队列的任务之前执行

因此,接下来我们将查找放置在 promise 作业队列(即微任务队列)中的作业

  • “LOG 7 - 立即解析”
  • “LOG 11 - 解决从 fn 返回的承诺:”

承诺作业队列中的作业可以在队列变空之前添加更多作业运行

所以接下来我们通过队列中已经执行过的promise作业获取放置在promise作业队列中的作业:

  • “LOG 8 - 不获取”)

超时回调作业的优先级低于 Promise 作业队列中的作业

所以现在可以执行来自定时器任务源的超时处理程序,因为承诺作业队列是空的:

“LOG 10 - setTimeout - 立即解决”)

  • “----------------------------(日志 2)”

获取日志

提取操作的日志何时出现取决于操作完成需要多长时间,但是

  • “LOG 5 - fetchedData 1st then - res.json()”会出现在前面
  • “LOG 6 - 带抓取”

根据实际输出,它们会在不到一秒内出现。

技术说明

运行 promise 处理程序以监视其行为并继续链式 promise 处理的任务在上面称为“Promise 作业”,因为这就是 ECMAScript 标准中的名称。

Promise 作业队列中的作业优先于其他任务,因为它们是 implemented in HTML5 using the microtask queue.


0
投票

传递给 setTimeout 等 API 的回调在任务队列中排队。任务队列中的函数只会运行,一旦调用堆栈为空并且没有更多的同步代码要执行。

Promise 表现不同。通过使用 .then() 或 async/await,您可以将函数设置为在 promise 解决后执行。这些函数将转到不同的队列(微任务队列),并在当前堆栈完成其同步代码后立即执行。

© www.soinside.com 2019 - 2024. All rights reserved.