Promise 以及 async/await 是什么

发布时间:2019-08-27 22:08

AJAX的出现使浏览器的用户体验得到了一个质的提升,再不用像以前一样(例如:查看下一页必须整个页面全部重新加载,使用AJAX只需要局部加载下一页数据然后重新渲染DOM)。

当然AJAX是一个异步操作,当请求成功之后,调用一个回调函数。在遇到需要获取返回内容时再做其他操作,很容易陷入“回调地狱”。这个词相信都不陌生也经常遇到这种情况,最好的做法就是封装一层AJAX参数处理、传入回调函数,做一些简单的封装。

那么接下来就要介绍一下 Promise ,它是个什么东西,干吗用的 …

Promise

首先查看一下官方文档资料

Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值。

很显然这是一个进行异步操作的函数,并且在操作结束后返回一个状态,成功或者失败。试一下怎么使用吧

DEMO 1

  1. function newPromise() {
  2. return new Promise((resolve, reject) => {
  3. resolve("我调用then方法");
  4. reject("我调用catch方法");
  5. })
  6. }
  7. let p = newPromise();
  8. console.log(p);
  9. p.catch((res) => {
  10. console.log(res);
  11. }).then((res) => {
  12. console.log(res);
  13. })

Promise 需要传入一个函数,这个函数接收两个方法,分别是 resolve ,reject ,对应着 Promise 的 prototype 上的 then 以及 catch。

resolve : 用于返回一个成功状态,并且传入的值最终由then方法执行

reject : 用于返回一个失败状态,并且传入的值最终由catch方法执行

我们log一下(resolve,reject 只执行前面一个,所以想看到效果得分开执行)

我们发现当执行 resolve 方法时 Promise 的 then 方法也是执行了的 但是并没有返回值。

DEMO 2

  1. function getName() {
  2. return new Promise((resolve, reject) => {
  3. let name = "Tom";
  4. console.log(name);
  5. setTimeout(function () {
  6. name = "Jack";
  7. resolve(name);
  8. }, 2000);
  9. console.log(name);
  10. })
  11. }
  12. let name = getName();
  13. console.log(name);
  14. name.catch((res) => {
  15. console.log(res);
  16. }).then((res) => {
  17. console.log(res);
  18. })

我们使用了一个 setTimeout 模拟一次请求,返回 “Jack” 并保存在 name 变量上,然后使用 resolve 方法把“请求”回来的是传给 then 方法,log一下。

因为 setTimeout 是一个异步操作,所以直接打印出两次“Tom”,然后输出一个 Promise 对象,在 2s 之后执行了 then 方法,打印出了 “Jack”,这也就是 Axios HTTP 库 的实现原理了。

Axios 部分代码:

  1. module.exports = function xhrAdapter(config) {
  2. return new Promise(function dispatchXhrRequest(resolve, reject){
  3. ......
  4. });
  5. };

async

官方文档资料

async function 声明用于定义一个返回 AsyncFunction 对象的异步函数。异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的 Promise 返回其结果。但是如果你的代码使用了异步函数,它的语法和结构会更像是标准的同步函数。

可能这个看着有点绕,简单一点就是,async function 的声明函数方式会把这个函数定义成异步函数,它会返回一个 Promise 对象,我们可以把 async 理解为 Promise 的语法糖。

DEMO 3

  1. async function asyncFun() {
  2. console.log("我是一个异步方法");
  3. }
  4. let fun = asyncFun();
  5. console.log(fun);
  6. fun.catch((res) => {
  7. console.log(res);
  8. }).then((res) => {
  9. console.log(res);
  10. });

asyncFun 返回了一个 Promise 对象,但是 then 方法输出了 undefined,这是因为 asyncFun 方法中我们没有 return 所以默认返回 undefined

await

官方文档资料

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

这个就很直接了,等待 Promise 对象返回他的信息,但是只能在 async 声明的函数中使用;

DEMO 4

  1. function getName() {
  2. return new Promise((resolve, reject) => {
  3. let name = "Tom";
  4. setTimeout(function () {
  5. name = "Jack";
  6. resolve(name);
  7. }, 2000);
  8. })
  9. }
  10. async function asyncFun() {
  11. let name = await getName();
  12. console.log(name);
  13. }
  14. asyncFun();

还是那个获取 name 的放法 看一下输出值

2s 之后输出日志 “Jack”。

使用了 await 之后 我们获取到 getName 的返回值,在之前需要 then 方法,现在可以用“看起来像”同步的方式获取了,为什么说看起来像同步呢,因为 asyncFun 它还是一个异步函数。

DEMO 5

  1. async function asyncFun() {
  2. let name = await getName();
  3. console.log(name);
  4. return name;
  5. }
  6. console.log(asyncFun());

想一下,能输出 “Jack”吗???

其实并不能,asyncFun 是一个异步函数,所以返回的依旧是一个 Promise 对象(仿佛陷入了一个死循环一样)。

以上就是全部内容了,这也是我在使用Axios 以及 anync/await 遇到的一些问题,花了点时间完全了解了一下这些东西的原理。

ps:没想到居然花了3个多小时整理