在很长一段时间里面,FE 们不得不依靠回调来处理异步代码。使用回调的结果是,代码变得很纠结,不便于理解与维护,值得庆幸的是 Promise 带来了. then(),让代码变得井然有序,便于管理。于是我们大量使用,代替了原来的回调方式。但是不存在一种方法可以让当前的执行流程阻塞直到 promise 完成。JS 里面,我们无法直接原地等 promise 完成,唯一可以用于提前计划 promise 完成后的执行逻辑的方式就是通过 then 附加回调函数。 现在随着 Async/Await 的增加,可以让接口按顺序异步获取数据,用更可读,可维护的方式处理回调。
Async/Await 是一个期待已久的 JavaScript 特性,让我们更好的理解使用异步函数。它建立在 Promises 上,并且与所有现有的基于 Promise 的 API 兼容。那么下面我来学习下这两个函数吧,lets go~
1、Async—声明一个异步函数 (async function someName(){...})
- 自动将常规函数转换成 Promise,返回值也是一个 Promise 对象
- 只有 async 函数内部的异步操作执行完,才会执行 then 方法指定的回调函数
- 异步函数内部可以使用 await
2、Await—暂停异步的功能执行 (var result = await someAsyncCall();)
- 放置在 Promise 调用之前,await 强制其他代码等待,直到 Promise 完成并返回结果
- 只能与 Promise 一起使用,不适用与回调
- 只能在 async 函数内部使用
3、使用小贴士:async 函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 await 命令就是内部 then 命令的语法糖。
如何来用呢?我们一起来敲一敲代码吧~
1、async 函数的几种使用形式
2、await 的用法则相对简单了许多,他后面需要是一个 Promise 对象,如果不是则会被转成 Promise 对象。只要其中一个如果 Promise 对象变为 reject 状态,那么整个 async 函数都会中断操作。如果状态是 resolve,那么他的返回值则会变成 then 里面的参数,如下。
3、使用小贴士
- 怎样容错呢,犹豫 await 后面的 promise 运行结果可能是 rejected,最好把 await 放入 try{}catch{} 中
- Await 后的异步操作,如果彼此没有依赖关系最好同时触发,在下面场景一会有介绍
- Await 只能在 async 函数之中,如果在普通函数中,会报错
那么什么情况下适合用,什么情况下不适合使用呢?
1、场景一,我们同时发出三个不互相依赖的请求,如果用 Async/Await 就显得不明智了
如上图所示,上面我们 A 需要 2s,B 需要 4s,C 需要 3s,我们如上图所示发请求,就存在彼此依赖的关系,c 等 b 执行完,b 等 a 执行完,从开始到结束需要(2+3+4)9s。
此时我们需要用 Promise.all() 将异步调用并行执行,而不是一个接一个执行,如下所示:
这样将会节省我们不少的时间,从原来的的 9s 缩减到 4s,是不是很开心,耶~
2、场景二,我曾经遇到过一个场景,一个提交表单的页面,里面有姓名、地址等巴拉巴拉的信息,其中有一项是手机验证码,我们不得不等待手机验证码接口通过,才能发出后续的请求操作,这时候接口之间就存在了彼此依赖的关系,Async 跟 Await 就有了用武之地,让异步请求之间可以按顺序执行。
其中不用 Async/Await 的写法,我们不得不用. then() 的方式,在第一个请求验证码的接口有返回值之后,才能执行后续的的 Promise,并且还需要一个 then 输出结果,如下图:
而用 Async/Await 的方式去写就是下面这样,我们将逻辑分装在一个 async 函数里。这样我们就可以直接对 promise 使用 await 了,也就规避了写 then 回调。最后我们调用这个 async 函数,然后按照普通的方式使用返回的 promise。要记得容错呢~~
以上是两个模拟简单的场景,为的是让大家容易理解 Async/Await 的使用,那么接下来我们看看兼容性吧~
Async / Await 已经在大多数主流浏览器中可用。
Async/Await 让我们用少量的代码来使用 Promise,我们可以将一些有依赖关系的回调函数的处理逻辑放在 async 里面,然后在非 async 的区域使用,这样可以减少 then 或者 catch 回调。
——————————————————
长按二维码,关注大转转 FE
来源: https://juejin.im/entry/5a44d5bf6fb9a044fb0810c2