第三十节: ES6 async与await

1.async 函数 & await

1.1. async含义

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

async 函数是 Generator 函数的语法糖。

什么是语法糖?

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

反向还有语法盐:

主要目的是通过反人类的语法,让你更痛苦的写代码,虽然同样能达到避免代码书写错误的效果,但是编程效率很低,毕竟提高了语法学习门槛,让人齁到忧伤。。。


1.2. async的使用

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

async function show (){
    await '33'
}
let p1 = show();


1.2.1 await配合async使用
async function fn(){  // async 表示异步,这个函数里面有异步的任务
    let result = await xxxx;  // 表示等待await后面的结果需要等待,等出来在处理
}


1.3. async函数对 Generator 函数的区别:

(1)内置执行器。

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

(2)更好的语义。

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

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

(4)返回值是 Promise。

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

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


1.4. async 的特点
  1. await 只能放到async函数中使用
  2. 相比generator 语义化更强
  3. await后面可以是promise对象,也可以是数字,字符串,布尔值
  4. async 函数返回的是一个promise对象
  5. 只要await 语句后面的Promise的状态变成reject,那么整个async函数会中断执行

1.4.1 验证async函数返回一个promise对象
async function fn(){

}
console.log(fn());  //Promise

// 使用
async function fn(){
    return 'welcome';
}
fn().then(res => {
    console.log(res);    // welcome
})


1.4.2 如果async函数中出错
async function fn(){
    throw new Error('Error 出错了')
}
fn().then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);  //  Error 出错了
})


1.4.3 如果await后面的语句出错,函数后面将中断执行

错误在成功之后,错误和成功都会执行

async function fn(){
    let a = await Promise.resolve("成功了");
    console.log(a);
    await Promise.reject('出错了')
}
fn().then(res => {
    console.log(res);   
}).catch(err => {
    console.log(err);
})
// 打印结果
// 成功了
// 出错了

但是如果错误在前,成功将不会执行

async function fn(){
    await Promise.reject('出错了')
    let a = await Promise.resolve("成功了");
    console.log(a);
}
fn().then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);   
})
// 打印结果
// 出错了


1.5. 解决async函数中的报错

如何解决async函数中抛出错误,影响后续代码执行;

这个问题比较严重,虽然是async的特点,但是我又不知道程序什么时候出错,所以我不希望出错的代码影响我后续运行


1.5.1使用 try { } catch (){}
async function fn(){
    try{
        await Promise.reject('出错了')
    }catch(e){
        let a = await Promise.resolve("成功了");
        console.log(a);
    }
}


1.5.2 添加catch 捕获错误

本来await后面的就是promise,那么我们就可以直接使用catch处理

async function fn(){
    await Promise.reject('出错了').catch(err=>{
        console.log(err);
    })
    let a = await Promise.resolve("成功了");
    console.log(a);
}

其实跟网络打交道的都不保险,你不可能给每一个await后面的promise对象都加catch


1.5.3 统一捕获错误

个人建议,只要有await的地方都try catch掉 然后统一处理结果

try {
    let f1 = await Promise.resolve('成功了');
    let f2 = await Promise.resolve('成功了');
    let f3 = await Promise.reject('出错了');
}catch(e){}


1.5.4 也可以是用Promise.all()方法

如果你多次请求的数据之间没有关联,就可以使用Promise.all()

// async 
async function fn(){
    let [f1,f2,f3] = await Promise.all([
        Promise.resolve('成功了1'),
        Promise.resolve('成功了2'),
        Promise.resolve('成功了3')
    ])


    console.log(f1);
    console.log(f2);
    console.log(f3);
}
fn();

同时配合解构处理

例子:

async function show() {
    let p1 = await new Promise((res, rej) => {
        $.ajax({
            url: 'https://jsonplaceholder.typicode.com/todos/1',
            success: function (data) {
                console.log(data);
                res()
            },
            error: function (err) {
                rej()
            }
        })
    });

    let p2 = await new Promise((res, rej) => {
        $.ajax({
            url: 'https://jsonplaceholder.typicode.com/todos/2',
            success: function (data) {
                console.log(data);
                res()
            },
            error: function (err) {
                rej()
            }
        })
    });

}

let pp = show();

generator只是一个过渡期,强烈建议大家用async就可以了

你可能感兴趣的:(第三十节: ES6 async与await)