ECMAScript 6(十)

async

Posted by     "Jordon Li" on Wednesday, December 25, 2019

TOC

ECMAScript 6 简介

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

async & await

async

  • 基本用法: async 函数是什么?一句话,它就是 Generator 函数的语法糖。async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
    const asyncReadFile = async function () {
      const f1 = await readFile('/etc/fstab');
      const f2 = await readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };
    
    ===========
    
    const gen = function* () {
      const f1 = yield readFile('/etc/fstab');
      const f2 = yield readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };
    
  • async函数对 Generator 函数的改进:
    1. 内置执行器: Generator 函数的执行必须靠执行器, 而async函数自带执行器。也就是说,async函数的执行,与普通函数一样。
    2. 更好的语义: asyncawait,比起星号(*)和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
    3. 更广的适用性: co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值。
    4. 返回值是 Promiseasync函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

返回 Promise 对象

  • 基本用法: async函数返回一个 Promise 对象。async函数内部return语句返回的值,会成为then方法回调函数的参数。
    async function f() {
      return 'hello world';
    }
    
    f().then(v => console.log(v))
    // "hello world"
    

Promise 对象的状态变化

  • 基本用法: async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

await 命令

  • 基本用法: 正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。

错误处理

  • 基本用法: 如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject
    async function myFunction() {
      try {
        await somethingThatReturnsAPromise();
      } catch (err) {
        console.log(err);
      }
    }
    
    // 另一种写法
    async function myFunction() {
      await somethingThatReturnsAPromise()
      .catch(function (err) {
        console.log(err);
      });
    }
    

注意点

  • 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
    //继发
    let foo = await getFoo();
    let bar = await getBar();
    
    //并发
    // 写法一
    let [foo, bar] = await Promise.all([getFoo(), getBar()]);
    
    // 写法二
    let fooPromise = getFoo();
    let barPromise = getBar();
    let foo = await fooPromise;
    let bar = await barPromise;
    

「下次一定」

下次一定

使用微信扫描二维码完成支付