Javascript等待/异步执行顺序

时间:2019-05-15 16:06:32

标签: javascript async-await

因此,我正在努力答应Promise / await / async。我不明白为什么在执行go()时,会在console.log(coffee)之后立即显示“已完成”的警报。当所有函数都使用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();
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>

2 个答案:

答案 0 :(得分:1)

这里的问题是console.log并不总是像人们想象的那样同步。该规范仅要求console.log在开发人员控制台中显示消息,而不对消息的显示方式或时间提出任何要求。视您的浏览器而定,结果可能会有所不同,但是通常会实现以下内容:

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

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

答案 1 :(得分:1)

异步/等待正在按预期方式工作。只是控制台需要花费一些时间来更新或浏览器正在重新绘制,因此alert在重新绘制之前被触发。您可以使用所有alert而不是console.log进行验证。所有alert均以正确的顺序执行。如下例所示。

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

      alert(coffee); // ☕

      const wes = await getCoffee();
      alert(wes);

      const wordPromise = getCoffee();
      alert(wordPromise);

      alert("finish");
    } catch (e) {
      console.error(e); // 
    }
  }
go();