Promise、Generator、async/await关系

Promise

定义(取自MDN)

一个 Promise 对象代表一个在这个 promise 被创建出来时不一定已知的值。它让您能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。 这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。

简单来说就是Promise内部有三个状态,核心原理就是通过内部状态机利用状态和回调实现了异步功能。

一个Promise必然处于以下三种状态之一:

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled): 意味着操作成功完成。
  • 已拒绝(rejected): 意味着操作失败。

Promise支持链式调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const myPromise =
(new Promise(myExecutorFunc))
.then(handleFulfilledA,handleRejectedA)
.then(handleFulfilledB,handleRejectedB)
.then(handleFulfilledC,handleRejectedC);

// 或者,这样可能会更好...

const myPromise =
(new Promise(myExecutorFunc))
.then(handleFulfilledA)
.then(handleFulfilledB)
.then(handleFulfilledC)
.catch(handleRejectedAny);

Generator

生成器对象是由一个 generator function 返回的,并且它符合可迭代协议迭代器协议

1
2
3
4
5
6
7
8
function* gen() {
yield 1;
yield 2;
yield 3;
}

let g = gen();
// "Generator { }"

归属于ES6规范。其最大的作用就是暂停执行,借助于这个特性,就可以将异步写法改为同步写法。只需要yield Promise就可以实现同步写法。

async函数

async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。asyncawait关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise

1
2
3
async function name([param[, param[, ... param]]]) {
statements
}

归属于ES7规范。

其实质是Generator和Promise的语法糖,就是一个可以自行执行的generator 包裹了 一些Promise。

优雅处理async/await错误

方法一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
* @param { Promise } 传进去的请求函数
* @param { Object= } errorExt - 拓展错误对象
* @return { Promise } 返回一个Promise
*/
export function to(
promise,
errorExt
) {
return promise
.then(data => [null, data])
.catch(err => {
if (errorExt) {
const parsedError = Object.assign({}, err, errorExt)
return [parsedError, undefined]
}

return [err, undefined]
})
}

export default to

用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const handleLogin = async () => {
const [resErr, res] = await to(await request('/basic/login', {
usename: 'sunshine',
password: '123456'
}))
if (resErr) {
// fail do somthing
return
}
const [userErr, info] = await to(request('/basic/getuserinfo', {
id: res.id
}))
if (userErr) {
// fail do somthing
return
}
this.userInfo = info
}

优点:

  1. 不用写大量不优雅的try/catch 语句
  2. 遇到异常可以当场停止,而不是 await().catch((e) ⇒ {})这种去处理。若用catch去捕捉,那么catch里面是异步的,不会终止当前异常代码的执行。

缺点:

  1. 缺点就是所有的异步函数都要用这个封装方法去包裹执行

参考资料

MDN,原来好多别人说起来很厉害的东西,MDN上面都有文档。

腾讯云参考资料

思否资料 思否资料2

async/await 你是会用,但是你知道怎么处理错误吗?

【建议星星】要就来45道Promise面试题一次爽到底(1.1w字用心整理)

Promise.all源码实现

★★★Async/Await 原理解析【终极版】

Author: XavierShi
Link: https://blog.xaviershi.com/2022/02/21/Promise、Generator、async-await关系/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.