异步编程之async/await

652 阅读3分钟

异步编程之async/await

先导语

在上一节中我们学习了event-loop事件循环机制,这节我们来学习下异步编程之async/await。 大家应该都听说过一句话:async/await 是异步编程的终极解决方案。那么下面我们就来体验下async/await的魅力吧!

async

首先,我们先来看一段代码:

    console.log(async function(){})

在一个方法前面加上async关键字,然后打印出来,会得到怎样的结果呢?答案是:

[AsyncFunction (anonymous)] 返回的是结果表示这是一个异步的方法。可能大家感觉也没什么特别的,那我们再来看下面这段代码:

    console.log(async function () {});
    console.log(function () {
      return new Promise((resolve, reject) => {
        resolve(6);
      });
    });

得到的结果是:

image.png
从结果上,我们可以看出,只有加了async的方法才会返回 AsyncFunction,没有async关键字的方法返回的只是一个 Function 。
我们再改变下这段代码:

    console.log((async function () {})());
    console.log(
      (function () {
        return new Promise((resolve, reject) => {
          resolve(6);
        });
      })()
    );

这里我们把两个方法都变成了立即执行的方法,然后我们得到如下结果:

image.png 这里,我们得到两个Promise对象,但是这两个Promise对象的来历是不同的,第一个方法会返回一个Promise对象,是因为async关键字。第二个会返回Promise对象是因为我们在函数内部返回了一个Promise对象。
这里我们可以得到一个结论:async关键字会把一个方法声明为一个异步方法,并且会将方法返回的值包装成一个promise对象。async其实就是一个promise的语法糖封装!

await

关于await,这里我们先给出结论:
1. await会阻塞进程
2. await可以进行表达式求值
3. 使用await可以使异步操作内抛出的错误被try...catch捕获

接下来,我们就可以通过举例去挨个去验证await的这几个特点了。

1.jpeg

await会阻塞进程

    async function test() {
      await new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log("1");
          resolve("1");
        }, 1000);
      });
      console.log("2");
    }

    test();

代码输出结果为:

image.png

当我们把await去掉:

    async function test() {
      new Promise((resolve, reject) => {
        setTimeout(() => {
          console.log("1");
          resolve("1");
        }, 1000);
      });
      console.log("2");
    }
    
    test();

结果为:

image.png

从这两段代码的对比中,我们可以得到await会阻塞进程的结论。

await可以进行表达式求值

demo1:

    async function test() {
      let a = await new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve("1");
        }, 1000);
      });
      console.log(a);
    }

    test();

结果:

image.png

demo2:

    async function test() {
      let a = await (2 * 3 + 5);
      console.log(a);
    }

    test();

结果:

image.png

demo3:

    async function test() {
      let a = await new Promise((resolve, reject) => {
        setTimeout(() => {
          reject(new Error("test"));
        }, 1000);
      });
      console.log(a);
    }

    test();

结果:

image.png

使用await可以使异步操作内抛出的错误被try...catch捕

首先我们先来看看,没有使用await的时候,try...catch 是否可以捕获异步任务中抛出的错误。

    function test() {
      try {
        new Promise((resolve, reject) => {
          setTimeout(() => {
            reject(new Error("test"));
          }, 1000);
        });
      } catch (error) {
        console.log(error);
      }
    }

    test();

在浏览器中运行的结果:全局抛出一个错误!

image.png

加了await关键字的情况:

    async function test() {
      try {
        await new Promise((resolve, reject) => {
          setTimeout(() => {
            reject(new Error("test"));
          }, 1000);
        });
      } catch (error) {
        console.log(error);
      }
    }

    test();

结果:错误被catch方法捕捉到了!

image.png

结束语

关于async和await的理解就到这里了。那么,下次见。好好学习,天天向上!

8.jpg