美文网首页
async 函数

async 函数

作者: 如果俞天阳会飞 | 来源:发表于2021-09-09 19:56 被阅读0次

    来源:https://es6.ruanyifeng.com/#docs/async

    1 含义

    ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

    async 函数是什么?一句话,它就是 Generator 函数的语法糖。

    前文有一个 Generator 函数,依次读取两个文件。

    const fs = require('fs');
    
    const readFile = function (fileName) {
      return new Promise(function (resolve, reject) {
        fs.readFile(fileName, function(error, data) {
          if (error) return reject(error);
          resolve(data);
        });
      });
    };
    
    const gen = function* () {
      const f1 = yield readFile('/etc/fstab');
      const f2 = yield readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };
    

    上面代码的函数gen可以写成async函数,就是下面这样。

    const asyncReadFile = async function () {
      const f1 = await readFile('/etc/fstab');
      const f2 = await readFile('/etc/shells');
      console.log(f1.toString());
      console.log(f2.toString());
    };
    

    一比较就会发现,async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。

    async函数对 Generator 函数的改进,体现在以下四点。

    (1)内置执行器。

    Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。

    asyncReadFile();
    

    上面的代码调用了asyncReadFile函数,然后它就会自动执行,输出最后结果。这完全不像 Generator 函数,需要调用next方法,或者用co模块,才能真正执行,得到最后结果。

    (2)更好的语义。

    async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

    (3)更广的适用性。

    co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。

    (4)返回值是 Promise。

    async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

    进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。

    用法

    下面是另一个例子,指定多少毫秒后输出一个值。

    function timeout(ms) {
      return new Promise((resolve) => {
        setTimeout(resolve, ms);
      });
    }
    
    async function asyncPrint(value, ms) {
      await timeout(ms);
      console.log(value);
    }
    
    asyncPrint('hello world', 50);
    

    上面代码指定 50 毫秒以后,输出hello world。

    由于async函数返回的是 Promise 对象,可以作为await命令的参数。所以,上面的例子也可以写成下面的形式。

    语法

    返回promise对象

    async函数返回一个 Promise 对象。

    async函数内部return语句返回的值,会成为then方法回调函数的参数。

    async function f() {
      return 'hello world';
    }
    
    f().then(v => console.log(v))
    // "hello world"
    

    await 命令

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

    async function f() {
      // 等同于
      // return 123;
      return await 123;
    }
    
    f().then(v => console.log(v))
    // 123
    

    上面代码中,await命令的参数是数值123,这时等同于return 123。

    另一种情况是,await命令后面是一个thenable对象(即定义了then方法的对象),那么await会将其等同于 Promise 对象。

    class Sleep {
      constructor(timeout) {
        this.timeout = timeout;
      }
      then(resolve, reject) {
        const startTime = Date.now();
        setTimeout(
          () => resolve(Date.now() - startTime),
          this.timeout
        );
      }
    }
    
    (async () => {
      const sleepTime = await new Sleep(1000);
      console.log(sleepTime);
    })();
    // 1000
    

    相关文章

      网友评论

          本文标题:async 函数

          本文链接:https://www.haomeiwen.com/subject/liniwltx.html