zoukankan      html  css  js  c++  java
  • ECMAScript 6 学习(二)async函数

    1、什么是async函数

    2、用法

      2.1基本用法

    3、语法

      3.1返回promise对象

      3.2promise状态的变化

      3.3await命令

    1、什么是async函数

    async函数也是异步编程的解决方案。

    async函数是对是对generator函数进行了改进。

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

    后边的gen函数,写成async函数

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

    async函数就是将generator函数的星号(*)换成async,将yield替换成await。

     async函数对generator函数进行改进,体现以下四点。

    (1)内置执行器。

    generator函数的执行必须依靠执行器,而async函数自带执行器,也就是说,async函数的执行与普通函数一模一样,只要一行。

    下面代码调用了asyncReadFile函数,然后就会自动执行,输出最后的结果。这个完全不像generator函数,需要调用next方法,才能得到最终的结果。

    var result=asyncReadFile();

    (2)更好的语义

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

    (3)更广的适用性

    yield命令后面只能是Thunk函数或者promise对象,而async函数的await命令后面,可以是promise对象和原始类型的值(数值,字符串和布尔值,但这等同于同步操作)

    (4)返回值是promise

    async函数的返回值是promise对象,执行generator函数返回一个遍历器对象(Iterator对象)方便多了,也就是说,async函数可以看做是多个异步操作,包装成一个promise对象,而await命令是内部then命令的语法糖。

    2、用法

    2.1基本用法

    async函数返回的是一个promise对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

    举一个栗子

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

    上面代码指定5秒后输出hello world。

     async函数多种使用形式

    //函数声明
    async function foo() {}
    
    //函数表达式
    const foo = async function () {}
    
    //对象的方法
    let obj = { async foo() {} }
    obj.foo().then(...)
    
    //箭头函数
    const foo = async () => {};
    
    //class方法
    class Storage {
      constructor() {
        this.cachePromise = caches.open('avatars');
      }
    
      async getAvatar(name) {
        const cache = await this.cachePromise;
        return cache.match(`/avatars/${name}.jpg`);
      }
    }

    3、语法

     async函数的语法规则总体上比较简单,难点是错误处理机制。

    3.1返回的promise对象

    async函数返回的是promise对象。

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

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

    上面代码中,函数f内部return 命令返回值,会被then方法回调函数接收到。输出“hello world”。

    async函数内部抛出的错误,会导致返回的promise对象变成reject状态。抛出的错误对象会被catch方法回调函数接收到。

    3.2promise对象状态变化 

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

    举个栗子

    async function getTitle(url) {
      let response = await fetch(url);
      let html = await response.text();
      return html.match(/<title>([sS]+)</title>/i)[1];
    }
    getTitle('https://tc39.github.io/ecma262/').then(console.log)

    上面代码中,函数getTitle内部有三个操作:抓取网页,取出文本,匹配页面标题。只有三个操作全部完成,才会执行then方法里面console.log。

     3.3 await命令 

     正常情况下,await命令后边是一个promise对象。如果不是,会被转成一个一个立即resolve的promise对象。

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

    上面代码中,await命令的参数是数值123,他被转成promise对象,并立即resolve。

    await命令后边的promise对象如果变成reject状态,则reject的参数会被catch方法的回调函数接收到。

    举个栗子

    async function f() {
      await Promise.reject('出错了');
    }
    
    f()
    .then(v => console.log(v))
    .catch(e => console.log(e))

    上面代码中,await语句前面没有return,但是reject方法的参数依然传入catch方法的回调函数,这里如果在wawait前面加上return,效果是一样的。

     只要一个await语句后面的promise变成了reject,那么整个async函数都会中断执行。

    async function f() {
      await Promise.reject('出错了');
      await Promise.resolve('hello world'); // 不会执行
    }

    上面代码中,第二个await语句是不会执行的,因为第一个await语句状态变成了reject

  • 相关阅读:
    C# 中国日历 农历 阳历 星座 二十四节气 二十八星宿 节日 天干地支
    C# AutoMapper:流行的对象映射框架,可减少大量硬编码,很小巧灵活,性能表现也可接受。
    Asp.net webapi 判断请求参数是否为空简易方法 Model Validation 判断请求参数是否为空
    IIS本地部署局域网可随时访问的项目+mysql可局域网内访问
    jquery ajax return不起作用
    asp.net webapi 给字段赋初始值DefaultValue 解决前端传空字符串后台接受不是“”而是NULL
    git log的常用命令
    C++面试题集合(持续更新)
    python的with用法(转载)
    stage_ros的world文件配置方法
  • 原文地址:https://www.cnblogs.com/chengxs/p/7226343.html
Copyright © 2011-2022 走看看