Javascript等待/异步执行顺序

CI_*_*Guy 5 javascript async-await

所以我试图把我的头放在 promises/await/async 上。我不明白为什么当执行 go() 时,在 console.log(coffee) 之后会出现带有“finished”的警报。当所有函数都使用 await/promises 时,为什么它只等待 getCoffee() 而其他 axios 调用在“完成”警报之后运行?

function getCoffee() {
  return new Promise(resolve => {
    setTimeout(() => resolve("?"), 2000); // it takes 2 seconds to make coffee
  });
}
async function go() {
  try {
    alert("ok");
    const coffee = await getCoffee();

    console.log(coffee); // ?

    const wes = await axios("https://randomuser.me/api/?results=200");
    console.log("wes"); // using string instead of value for brevity

    const wordPromise = axios("https://randomuser.me/api/?results=200");
    console.log("wordPromise"); // using string instead of value for brevity

    alert("finish");
  } catch (e) {
    console.error(e); // 
  }
}
go();
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>
Run Code Online (Sandbox Code Playgroud)

ste*_*esu 4

这里的问题是console.log并不总是像人们想象的那样同步。该规范仅要求console.log在开发者控制台中显示一条消息,但没有对如何或何时显示消息做出任何要求。根据您的浏览器,结果可能会有所不同,但通常会实现如下所示的内容:

  • 当您调用请求时,console.log请求会被推送到堆栈队列中(因此连续调用console.log始终按顺序执行)
  • 在下一个动画帧上,浏览器将尝试处理尽可能多的堆栈队列(必须处理堆栈队列上的至少一个元素,因此如果您尝试记录 8 MB 的数据,浏览器可能会锁定)
  • “处理”堆栈队列涉及到将 DOM 元素引用转换为可带您进入开发控制台其他位置的链接、将 JSON 对象转换为可导航和可折叠的 UI 元素,或者用文本“[Object object]”替换对象
  • 一旦堆栈队列上的元素被处理,它就必须在控制台中呈现。这需要调整控制台的高度,确定是否需要滚动条,确定文本将在哪里换行等。这个过程(在控制台中获取您想要的内容并实际将其显示在屏幕上)称为“绘画”

因为console.log实际上是这样一个复杂的操作,所以在alert语句运行之前它可能无法完成执行(在某些浏览器中)。通过将每次调用替换alertconsole.log或每次调用,console.logalert应该会看到事情实际上是按预期顺序执行的。