Samgao0312 / Blog

MIT License
1 stars 1 forks source link

【再学前端】Promise与Async...await的区别 #141

Open Samgao0312 opened 2 years ago

Samgao0312 commented 2 years ago

问题:

1、什么是Promise

Promise是 es6 中增加的新特性,是一种引用类型,可以通过new操作符来实例化。它有以下几个特点:

  1. Promise是一个对象,对象和函数的区别就是对象可以保存状态,函数不可以(闭包除外)。
  2. 代码风格更简洁,容易理解,便于维护,更优雅。(相对回调嵌套写法)
  3. 提供了对异步请求结果和错误处理的相关API。
  4. 支持链式调用。
  5. Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。

优点:

缺点:

适用场景:

问题: 为什么在已经有了Promise的情况下,还要推出Async/await呢?

Async/await 是es8中提出的概念,它是为了简化Promise的.then() 操作。

2、什么是Async/await

Async/await是 es8 中引入的新语法,用来简化Promise的异步操作。 在async和await出现之前,开发者只能通过链式.then()的方式处理Promise异步操作。 Async/await 是Javascript编写异步程序的新方法。以往的异步方法无外乎回调函数和Promise。但是 Async/await 建立于 Promise之上。具有以下特定:

  1. async/await 是写异步代码的新方式(以前的方法有回调函数和Promise),相对Promise来讲写法更加优雅。
  2. async/await 是基于(建立在)Promise上实现的,它不能用在普通的回调函数。
  3. 如果某个方法的返回值是一个Promise实例对象,我们可以在它的调用的方法名前加await,最后这个方法返回值就不是Promise对象,而是一个具体的值。
  4. async/await 与Promise一样,是非阻塞的。
  5. async/await 使得异步代码看起来像同步代码,这正是它的魔力所在。 (异步编程的最高境界就是不关心它是否是异步。async/await很好的解决了这一点,将异步强行转换为同步处理)
  6. async函数会隐式地返回一个Promise,该promise的resolve值就是return的值。
  7. await 是等待的意思,其实它后面可以放任何表达式,不过我们更多的是放一个返回 promise对象的表达式,它等待的是 promise对象的执行完毕,并返回结果。
  8. await的必须在异步函数中使用;其中await有限制(不允许出现在箭头函数中;不允许出现在同步函数声明中;不允许出现在同步函数表达式中;如果在同步函数中使用await就会抛出SyntaxError。)
  9. await关键字只能出现在用async声明的函数体内,且这两个修饰符是成对出现的。
  10. 使用await可以直接获取结果,而不是一个promise对象。
  11. async函数返回的也是promise对象。
  12. 在主体函数之前使用了async关键字,在函数体内,使用了await关键字。
  13. 当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
  14. async和await关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。
  15. async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。
  16. 在async方法中,第一个await之前的代码会同步执行,await之后的代码会异步执行。

3、两者区别

  1. promise是es6新增的对象,async/await是es7中新加的支持。
  2. async/await相对于promise来讲,写法更加优雅。
  3. async/await 代码看起来像同步代码。
  4. reject状态:
  5. 1)promise错误可以通过catch来捕获,建议尾部捕获错误。
  6. 2)async/await既可以用.then,又可以用 try-catch捕捉。
  7. async/await 是建立在 Promises上的,不能被使用在普通回调。
  8. async/await 和 Promises 很像,不阻塞。

3.1 async/await方法更简洁

//promise:
const makeRequest = () =>
    getJSON()
        .then(data => {
            console.log(data)
            return "done"
        })
makeRequest()

//async/await :
const makeRequest = async () => {
    console.log(await getJSON())
    return "done"
}
makeRequest()

3.2 多个异步请求,且后面的异步请求依赖前面异步请求结果的场景

一个经常出现的场景是,我们先调起promise1,然后根据返回值,调用promise2,之后再根据这两个Promises得值,调取promise3。

适用Promise的实现:

//promise
const makeRequest = () => {
  return promise1().then((value1) => {
    // do something
    return promise2(value1).then((value2) => {
      // do something
      return promise3(value1, value2);
    });
  });
};

//我们可以使用Promise.all来避免很深的嵌套
const makeRequest = () => {
  return promise1()
    .then((value1) => {
      // do something
      return Promise.all([value1, promise2(value1)]);
    })
    .then(([value1, value2]) => {
      // do something
      return promise3(value1, value2);
    });
};

同样的场景,适用async/await会非常简单:

const makeRequest = async () => {
  const value1 = await promise1();
  const value2 = await promise2(value1);
  return promise3(value1, value2);
};

3.3 错误处理

Promise 中不能自定义使用 try/catch 进行错误捕获,但是在 Async/await 中可以像处理同步代码处理错误。

const makeRequest = () => {
  try {
    getJSON().then((result) => {
      // this parse may fail
      const data = JSON.parse(result);
      console.log(data);
    });
    // uncomment this block to handle asynchronous errors
    // .catch((err) => {
    //   console.log(err)
    // })
  } catch (err) {
    console.log(err);
  }
};

Async/await:

const makeRequest = async () => {
  try {
    // this parse may fail
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }
}


参考阅读