美文网首页前端知识收集
第三十节: ES6 async与await

第三十节: ES6 async与await

作者: 心存美好 | 来源:发表于2022-02-03 16:56 被阅读0次

1.async 函数 & await

1.1. async含义

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

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

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

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

1.2. async的使用

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

//创建异步函数
async function show() {
    let result =await 20;
    console.log(result);
  }   
  show()
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)更好的语义。

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

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

(4)返回值是 Promise。

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

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

  async function show() {
    let result =await new Promise((res)=>{   //后面跟Promise,里面定义一个回调函数。await会始终等到后面的Promise调用then方法,把then方法的值取出来赋值给result
      setTimeout(()=>{
        res(50)
      },3000)
    });
    console.log(result);
  }   
  show()
    async function show() {
      let result = await new Promise((res) => {   //后面跟Promise,里面定义一个回调函数。await会始终等到后面的Promise调用then方法,把then方法的值取出来赋值给result
        setTimeout(() => {
          res(50)
        }, 3000)
      });
      console.log(result);
      return result + 20;
    }
    show()
    let res = show();
    console.log(res);
    res.then((data) => { console.log(data); })
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 出错了
})
    async function show() {
      throw new Error('Error 出错了')
    }
    let res = show();
    console.log(res);
    res.then((data) => { console.log(data); })
      .catch(err => {
        console.log(err);  //  Error 出错了
      })
    async function show() {
      try {
        throw new Error('Error 出错了')
        let result = await 20;
        console.log(result);

      } catch (err) {
        console.log(err)
      }
    }
    let promise = show()
    promise.then((data) => console.log(data))
1.4.3 如果await后面的语句出错,函数后面将中断执行

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

async function fn(){
    let a = await Promise.resolve("成功了");
    console.log(a);
    await Promise.reject('出错了')   //await 后面如果是失败状态promise 这条语句后面的代码都不会执行
}
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();

同时配合解构处理

例子:

  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
  <script>
    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

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