ES6 async函数(超级详细、易懂)

下面是对 ES6 async函数的整理,希望可以帮助到有需要的小伙伴~

async函数是什么

ECMAScript 2017规范引入了async函数,该函数的主要目的是简化使用Promise异步调用的操作,并对一组Promise执行某些操作。

Promise类似于结构化回调

async、await类似于组合生成器和Promises。

await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用

function resolveAfter2Seconds() {
    return new Promise(resolve => {
        setTimeout(()=>{
            resolve('resolved');
        },2000);
    })
}

async function asyncCall() {
    console.log("calling"); // calling
    // 暂停当前asyncCall()函数的执行,等待Promise处理完成后再执行asyncCall()函数
    var result = await resolveAfter2Seconds();
    console.log(result); // resolved
}
asyncCall();

异步函数声明式

异步函数声明式用于定义一个返回Promise对象的异步函数。

异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的Promise返回其结果

异步函数的语法和结构与同步函数比较像。

async function name([param[, param[, ... param]ll) { statements }
  • name:函数名称
  • param:要传递给函数的参数的名称。
  • statements:表示函数体语句。

异步函数表达式

步函数表达式用于在表达式中定义异步函数。

let name = async function([param1[, param2[ .., paramN]]]) { statements }
  • name:表示函数名称。
  • pacam:要传递给函数的参数的名称。
  • statements:表示函数体语句。

异步函数表达式与异步函数语句声明式的区别:

于异步函数表达式可以省略函数名称来创建一个匿名函数。

返回Promise对象

async函数返回一个Promise对象

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

实例1:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JPVf9Xvg-1608908797743)(es6/async1.png)]

实例2:

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

// 等同于
f().then(
    function (v) {
        console.log(v); // hello world
    }
)

// 上述异步函数async function中没有await表达式,因为异步函数会先创建Promise对象,然后再执行

注意:

上述异步函数async function中没有await表达式,因为异步函数会先创建Promise对象,然后再执行

await表达式

await表达式用于等待一个Promise对象,它只能在异步函数中使用

[return .value] = await expression;
  • expression:一个Promise对象或者任何要等待的值。

  • return…alue

    • 如果等待的是Promise对象,返回Promise对象的处理结果(成功或失败)。
    • 如果等待的不是Promise 对象,则返回该值本身。
function createPromise(){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve("执行成功");
        },200);
    });
}


async function myAsync() {
    console.log("当前异步函数被调用");
    var result = await createPromise();
    console.log("Promise对象执行的结果:" + result);
}

myAsync(); // 调用异步函数

await处理错误

为了防止报错,使用try…catch语句

function createPromise(){
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            reject("执行失败");
        },200);
    });
}


async function myAsync() {
    console.log("当前异步函数被调用"); // 当前异步函数被调用
    try {
        // 执行后会出错的语句
        var result = await createPromise();
    } catch(e) {
        // 提示错误的语句
        console.log("Promise对象执行的结果:" + e); // Promise对象执行的结果:执行失败
    }

}

myAsync(); // 调用异步函数

async函数执行一组Promise

一组Promise对象的执行顺序只与async函数中await的顺序有关。

let promise1 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve("one");
    },300);
});

let promise2 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve("two");
    },200);
});

let promise3 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve("three");
    },100);
});

async function myAsync() {
    let result1 = await promise1;
    console.log(result1);

    let result2 = await promise2;
    console.log(result2);

    let result3 = await promise3;
    console.log(result3);
}
myAsync();


// Promise对象执行的顺序与设置的延迟时间没有关系,Promise对象执行的顺序只与async函数中的顺序有关

注意事项

使用try…catch语句

await命令后面的Promise 对象,运行结果可能是rejected,有2种处理错误的方法

  1. try…catch语句
  2. Promise的catch语句

实例:

function fun() {
    return new Promise((resolve,reject) => {
        reject("执行失败");
    })
}

// try...catch处理错误
async function myAsync1() {
    try {
        await fun();
    }catch (e) {
        console.log(e);
    }
}

myAsync1(); // 执行失败

// catch处理错误
async function myAsync2() {
    await fun().catch(function (err) {
                    console.log(err);
    })
}

myAsync2(); // 执行失败

多个await同时触发

多个await表达式后面的异步操作,如果不存在继发关系,最好让它们同时触发。

let promise1 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve("one");
    },300);
});

let promise2 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve("two");
    },200);
});

let promise3 = new Promise((resolve,reject) => {
    setTimeout(() => {
        resolve("three");
    },100);
});

// promise1,promise2,promise3依次独立的异步操作
/*async function myAsync() {
    let result1 = await promise1;
    console.log(result1);

    let result2 = await promise2;
    console.log(result2);

    let result3 = await promise3;
    console.log(result3);
}
myAsync();*/

// Promise对象执行的顺序与设置的延迟时间没有关系,Promise对象执行的顺序只与async函数中的顺序有关

// promise1,promise2,promise3同时执行异步操作
async function myAsync3() {
    let [result1,result2,result3] = await Promise.all([promise1,promise2,promise3]);
    console.log(result1,result2,result3)
}
myAsync3(); // one two three

promise1,promise2,promise3是3个独立的异步操作(即互不依赖),被写成继发关系一个一个的进行异步操作是比较耗时间的,可以让promise1,promise2,promise3同时触发,同时进行异步操作(同时触发的条件:promise1,promise2,promise3按顺序执行)。

await表达式的限制

await表达式只能用在async函数之中,如果用在普通函数,就会报错。

async function f1() {
    let docs = [{},{},{}];

    // 报错
    docs.forEach(function (doc) {
        await db.post(doc); // SyntaxError: await is only valid in async function 翻译:SyntaxError: await只在异步函数中有效
    })
}

Symbol

ECMAScript 6新增了第六种原始类型Symbol(符号)类型。

Symbol类型是唯一的并且是不可修改的,并且也可以用来作为Object 的 key 值。

Symbol类型的变量是通过调用Symbol()函数生成的:

Symbol([description])
  • description:可选的字符串。Symbol的描述,可用于调试但不能访问Symbol本身。

注意:

由于Symbol类型是原始类型,是不能通过new Symbol()来创建对象的。

实例:

/*
    ES5 的 5种原始类型
    * string - String
    * number - Number
    * string - String
    * undefined - Undefined
    * null - Null
    ES6 新增一种原始类型
    Symbol
*/

let num = 100;  // new Number()
let str = "软件学院"; // new String()
let boo = true;
/*
    symbol类型是ES6新增的第六种原始类型
    Symbol类型是唯一的并且是不可修
    let symbol = Symbol()
    原始类型是不能创建对象的
*/

let symbol = Symbol();
console.log(typeof symbol); // symbol 判断原始类型必须使用typeof

let symbol2 = Symbol("xxx");
console.log(symbol2); // Symbol(xxx)
let symbol3 = Symbol(5);
console.log(symbol3); // Symbol(5)

// 修改变量的值,而不是修改类型,Symblo是不能转为其它类型的
symbol3 = Symbol("yyy");
console.log(symbol3); // Symbol(yyy)


Symbol的注意事项

当使用Symbol值进行类型转换时需要注意一些事情:

  • 尝试将一个symbol值转换为一个number值时,会抛出一个工ypeError错误。
  • Object(symbol) == symnbol表达式的结果返回true。
  • 阻止从一个symbol 值隐式地创建一个新的string类型的属性名。
Symbol的方法
  • Symbol.for()方法

    该方法会根据给定的键key,从symbol注册表中查找指定的key。

    • 如果找到了,则返回它。
    • 如果没有找到,新建一个与该键关联的 symbol,并放入全局symbol注册表中。
    Symbol.for(key);
    
    • 一个字符串,作为symbol注册表中与某symbol关联的键。

    • Symbol.for()方法与Symbol()的不同:

      • 用Symbol.for()方法创建的的symbol会被放人一个全局symbol注册表中
      • 用Symbol()方法创建的的symbol不会被放人一个全局symbol注册表中

    注册表是一个典型的键值对key : value集合

    举例:

    kye - 存储的方式

    value - 当前安装的软件

  • Symbol.keyFor()方法

    该方法用于获取symbol注册表中与某个symbol关联的键。

    Symbol.keyFor(sym);
    
    • sym:存储在symbol注册表中的某个symbol.
Symbol与for…in

Symbols 在 for…in迭代中不可枚举。

Object.getOwnPropertyNames()不会返回symbol对象的属性,但是可以使用Object.getOwnPropertySymbols()得到它们.

var obj = {};
// 如果Symbol作为对象的属性名,属性名是不可枚举的
obj[Symbol("a")] = "a";
obj[Symbol.for("b")] = "b";
obj["c"] = "c";
obj.d = "d";

for (var i in obj) {
    console.log(i); // c d 用Symbol作为对象的属性名的a和b是没有办法被枚举的
}

end 结束啦~
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值