做比萨的人解释JavaScript中的异步和等待

92 阅读4分钟

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

我们在日常工作中都会用到async和await。

什么是异步任务?

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

下面是一些日常的异步任务的例子

例子1:

你在汽车餐厅点餐,这时你的食物请求开始了(一个异步任务)。

当你的食物被准备好的时候,你在驾车通道的队伍中往前拉(下一个任务)。

你不需要等待你的食物准备好了才可以向前拉。

你正在等待你的食物,你的请求在取餐窗口得到了满足。

例子2。

你在你的厨房里拖地。

当你等待厨房的地板干燥时,你用真空吸尘器吸卧室的地毯。

原来的任务是清洁你的厨房地板,当地板干了以后,任务就完成了。

站着等地板干并不是太有成效,所以你在厨房地板干的时候吸了卧室的地板。

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

异步/等待的例子--烤一个冷冻比萨饼

你决定用你的烤箱烤一个比萨饼,你的第一步是预热烤箱。

所以你设置了所需的温度并开始预热烤箱。

在烤箱预热的时候,你从冰箱里拿出冷冻比萨,打开盒子,把它放在比萨盘上。

你还有时间!

也许你可以拿起饮料,在等待烤箱准备好时看一些电视。

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

// This async function simulates the oven response
const ovenReady = async () => {
  return new Promise(resolve => setTimeout(() => {
    resolve('Beep! Oven preheated!')
  }, 3000));
}

// Define preheatOven async function
const preheatOven = async () => {
  console.log('Preheating oven.');
  const response = await ovenReady();
  console.log(response);
}

// Define the other functions
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.');

// Now call the functions
preheatOven();
getFrozenPizza();
openFrozenPizza();
getPizzaPan();
placeFrozenPizzaOnPan();
grabABeverage();
watchTV();

// Output sequence in console:
Preheating oven.
Getting pizza.
Opening pizza.
Getting pan.
Putting pizza on pan.
Grabbing a beverage.
Watching television.
Beep! Oven preheated!

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

当我们await 等待异步的preheatOven 函数完成时,我们可以执行同步任务,如getFrozenPizza,openFrozenPizza,getPizzaPan,placeFrozenPizzaOnPan,grabABeverage 甚至watchTV

我们一直在执行这样的异步任务

而这也是async Javascript的工作方式。

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

要记住两个关键点。

  1. Javascript不会等待像preheatOven 这样的async 函数完成,然后再进入后面的任务,如getFrozenPizzaopenFrozenPizza
  2. await Javascript会在async ,如ovenReady ,完成并返回数据后再进入父异步函数的下一个任务。当console.log(response) 语句不执行,直到ovenReady 返回一个响应时,我们就会看到这一点。

如果比萨饼的例子不能说明问题...

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

因此,我将在下面提供一个不太抽象的异步和等待的JavaScript例子,用Fetch API请求数据。

JavaScript中的异步/等待代码示例

const getTheData = async () => {
    try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) throw Error();
    const data = await response.json();
    // do something with this data... save to db, update the DOM, etc.
    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。

我知道要完全掌握它可能需要一段时间。

开始为你渴望的披萨预热你的烤箱,在你等待提示音的时候,再看一些异步和等待的例子吧!

我把我的Youtube频道上的一个教程留给你。该视频给出了更深入的解释和更多的代码例子,包括对回调、承诺、thenables和Fetch API以及async & await的讨论。


Dave Gray

戴夫-格雷

你好,我目前正在攻读信息系统的博士学位。也是一个全职的解决方案架构师和开发人员。"努力追求进步,而不是完美"。在Twitter上关注我。@yesdavidgray


如果你读到这里,请发推特给作者,向他们表示你的关心。鸣谢

免费学习代码。freeCodeCamp的开源课程已经帮助超过40,000人获得开发工作。开始吧