zoukankan      html  css  js  c++  java
  • 前端知识点回顾之重点篇——ES6的async函数和module

    async函数

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

    async 函数是 Generator 函数的语法糖

    什么是语法糖?

    意指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖往往给程序员提供了更实用的编码方式,有益于更好的编码风格,更易读。不过其并没有给语言添加什么新东西

    async函数使用时就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已

    async函数对 Generator 函数的区别:

    (1)内置执行器。

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

    (2)更好的语义。

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

    (3)正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。

    (4)返回值是 Promise。

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

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

    用法如下:

    let task1 = function(){
        return new Promise((res, rej)=>{
            setTimeout(() => {
                res("完成task1");
            }, 1000);
        });
    }
    let task2 = function(str){
        return new Promise((res, rej)=>{
            setTimeout(() => {
                res(str+"完成task2");
            }, 2000);
        });
    }
    let task3 = function(str){
        return new Promise((res, rej)=>{
            setTimeout(() => {
                res(str+"完成task3");
            }, 3000);
        });
    }
    async function f() {
        let t1 = await task1();  //在这里await返回的是promise中resolve方法的参数
        console.log(t1, typeof t1);  //完成task1 string
        let t2 = await task2(t1);
        console.log(t2);
        return task3(t2);  //最后用return,表示将结果作为返回的Promise对象的resolve的参数
    }
    f().then(data=>{console.log(data)});  //完成task1完成task2完成task3
    

    错误处理

    如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。防止出错的方法,也是将其放在try...catch代码块之中。

    async function main() {
      try {
        const val1 = await firstStep();
        const val2 = await secondStep(val1);
        const val3 = await thirdStep(val1, val2);
    
        console.log('Final: ', val3);
      }
      catch (err) {
        console.error(err);
      }
    }
    

    Module

    ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict";。

    模块功能主要由两个命令构成:export和import。

    export命令用于规定模块的对外接口。

    import命令用于输入其他模块提供的功能。

    export

    一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。

    export输出遍历的写法一:

    // profile.js
    export var firstName = 'Michael';
    export var lastName = 'Jackson';
    export var year = 1958;
    

    写法二(推荐):

    // profile.js
    var firstName = 'Michael';
    var lastName = 'Jackson';
    var year = 1958;
    
    export {firstName, lastName, year};
    //跟上面写法等价,推荐这种写法。
    

    可以使用as关键字重命名:

    function v1() { ... }
    function v2() { ... }
    
    //export 内部参数 as 外部调用名
    export {
      v1 as streamV1,
      v2 as streamV2,
      v2 as streamLatestVersion
    };
    

    export语句输出的接口,与其对应的值是动态绑定关系,即通过该接口,可以取到模块内部实时的值。

    export var foo = 'bar';
    setTimeout(() => foo = 'baz', 500);
    //上面代码输出变量foo,值为bar,500 毫秒之后变成baz。
    

    export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错,下面的import命令也是如此。

    import

    使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

    下面代码的import命令,用于加载profile.js文件,并从中输入变量。import命令接受一对大括号,里面指定要从其他模块导入的变量名。大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

    // main.js
    import {firstName, lastName, year} from './profile';
    

    如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。

    //import 外部变量 as 内部参数
    import { lastName as surname } from './profile';
    

    注意,import命令具有提升效果,会提升到整个模块的头部,首先执行。

    foo();
    
    import { foo } from 'my_module';
    //import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。
    

    除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。注意,模块整体加载所在的那个对象,不允许运行时改变。下面的写法都是不允许的。

    import * as circle from './circle';
    
    // 下面两行都是不允许的
    circle.foo = 'hello';
    circle.area = function () {};
    

    export default

    使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。

    为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

    // export-default.js
    export default function () {
      console.log('foo');
    }
    

    其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

    // import-default.js
    import customName from './export-default';
    customName(); // 'foo'
    

    export default命令用在非匿名函数前,也是可以的。下面代码中,foo函数的函数名foo,在模块外部是无效的。加载的时候,视同匿名函数加载。

    // export-default.js
    export default function foo() {
      console.log('foo');
    }
    
    // 或者写成
    function foo() {
      console.log('foo');
    }
    export default foo;
    

    export default命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。所以,import命令后面才不用加大括号,因为只可能唯一对应export default命令。

  • 相关阅读:
    有关HL7 的C# 源码
    EF中调整字段的顺序
    xml schema 中如何定义类似Map的结构
    js将时间转换为时间戳
    postman使用
    H5拖拽
    读取XML文件中获取特定值
    读取XML文件
    owin使用
    C#跨线程访问
  • 原文地址:https://www.cnblogs.com/simpul/p/11020250.html
Copyright © 2011-2022 走看看