原文:Async and Await in JavaScript Explained by Making Pizza,作者:Dave Gray

async 和 await 可能听起来很复杂……但是一旦你深入了解它们,它们就像比萨饼一样简单。

我们都在日常生活中使用 async 和 await。

什么是异步任务

异步任务可让你在完成一个任务的同时完成其他任务。

以下是一些日常异步任务示例

示例 1:


你在驾车时订购食物,这会启动你的食物请求(异步任务)。

在准备食物的同时,你在保持向前(下一个任务)。

你不必等待食物准备好就可以前进。

你正在等待食物,你的要求在取货窗口得到满足。

示例 2:

你在厨房拖地。当你等待厨房地板干燥时,可以用吸尘器清理卧室的地毯。

最初的任务是清洁你的厨房地板,当地板干燥时,任务就完成了。

站在原地等待地板干燥的效率并不高,因此你在等待厨房地板干燥的同时用吸尘器清理卧室地板。

这也是 Javascript 处理异步函数的方式。

Async/Await 示例——烤冷冻比萨

你决定在烤箱中烤披萨,第一步是预热烤箱。因此,你设置了所需的温度并开始预热烤箱。

当烤箱预热时,你将冷冻披萨从冰箱中取出,打开盒子,然后将其放在披萨盘上。

你还有时间!

也许在等待烤箱准备好时发出哔哔声的同时,你可以喝一杯饮料并看一些电视节目。

下面是一些代码来模拟这个例子:

// 这个 async 函数模拟烤箱响应
const ovenReady = async () => {
  return new Promise(resolve => setTimeout(() => {
    resolve('Beep! Oven preheated!')
  }, 3000));
}

// 定义 preheatOven async 函数
const preheatOven = async () => {
  console.log('Preheating oven.');
  const response = await ovenReady();
  console.log(response);
}

// 定义其他函数
const getFrozenPizza = () => console.log('Getting pizza.');
const openFrozenPizza = () => console.log('Opening pizza.');
const getPizzaPan = () => console.log('Getting pan.');
const placeFrozenPizzaOnPan = () => console.log('Putting pizza on pan.');
const grabABeverage = () => console.log('Grabbing a beverage.');
const watchTV = () => console.log('Watching television.');

// 调用函数
preheatOven();
getFrozenPizza();
openFrozenPizza();
getPizzaPan();
placeFrozenPizzaOnPan();
grabABeverage();
watchTV();

// 在控制台按顺序输出:
Preheating oven.
Getting pizza.
Opening pizza.
Getting pan.
Putting pizza on pan.
Grabbing a beverage.
Watching television.
Beep! Oven preheated!

上面的过程正是 async 和 await 的全部内容。

当我们等待(await)异步 preheatOven 函数完成时,我们可以执行同步任务,如 getFrozenPizzaopenFrozenPizzagetPizzaPanplaceFrozenPizzaOnPangrabABeverage,甚至 watchTV

我们就是这样执行异步任务的

这也是异步 Javascript 的工作原理。

请注意,当我们 await 来自 async 函数的响应时,需要在另一个 async 函数中调用它。这就是我们在上面看到的,在 preheatOven 内部调用 ovenReady

要记住的两个关键点:

  • Javascript 不会等待像 preheatOven 这样的异步函数完成,然后才会继续执行 getFrozenPizzaopenFrozenPizza 等后续任务。
  • 在继续执行父异步函数中的下一个任务之前,Javascript 将等待(await)像 ovenReady 这样的 async 函数完成并返回数据。当 console.log(response) 语句在 ovenReady 返回响应之后才执行时,我们会看到这一点。

我知道日常示例对我们中的一些人有帮助,但其他人可能更喜欢真正的代码。

因此,我将在下面提供一个不太抽象的 async 和 await JavaScript 示例,该示例使用 Fetch API 请求数据:

JavaScript 中的 Async/Await 示例

const getTheData = async () => {
    try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) throw Error();
    const data = await response.json();
    // 用这些数据做点什么……保存到数据库,更新 DOM 等。
    console.log(data);
    console.log('You will see this last.')
    } catch (err) {
        console.error(err);
    }
} 

getTheData();
console.log('You will see this first.');

总结

我希望我已经帮助你理解了 JavaScript 中的 async 和 await。

我知道要完全掌握可能需要一段时间。开始为你想要的披萨预热烤箱,并在等待哔哔声的同时查看更多 async 和 await 示例吧!

下面是我发布在 Youtube 频道的教程。该视频提供了更深入的解释和更多代码示例,包括对回调、promises、thenables、Fetch API 以及 async 和 await 的讨论: