JavaScript-Promise
mindmap root[Promise] base(Promise 基础) advantagesAndDisadvantages))Promise 优缺点(( promiseState))Promise 状态(( PromiseResult))Promise 结果(( API(Promise API) m1)静态方法( then["Promise.prototype.then()"] catch["Promise.prototype.catch()"] finally["Promise.prototype.finally()"] m2)实例方法( resolve["Promise.resolve()"] reject["Promise.reject()"] all["Promise.all()"] race["Promise.race()"] any["Promise.any()"] allSettled["Promise.allSettled()"] problem))Promise 自定义封装(( async&await )async and await(
Promise 是 ES6 规范新增技术,是用来封装一个异步操作,并获取其成功/失败结果值。是 JS 中进行异步编程的最新解决方案(Promise 之前采用回调函数)
Promise 基础
Promise 的优点
- Promise 支持链式调用,解决回调地狱问题
回调地狱 —— 回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件。
回调函数不便于阅读;不便于异常处理 - 指定回调函数的方式更加灵活
- 是一个
构造函数
; - 用来封装一个异步操作
- 可以获取成功/失败状态和结果值
PromiseState,PromiseResult
。
new Promise(excutor)
- excutor 函数,是一个执行器
(resolve, reject) =>{}
。该执行器中封装异步代码。 - resolve 函数,内部定义成功时调用
- reject 函数,内部定义失败时调用
1 | // 打印 Promise 实例对象 |
Promise 的状态 [[PromiseState]]
Promise 的状态有三种:
- Pending 等待状态
- 已完成状态
- Fulfilled
- rejected
flowchart LR subgraph 等待状态 Pending end subgraph 已完成状态 fulfilled rejected end Pending --> fulfilled Pending --> rejected
修改 Promise 状态的几种方式:
- 调用 resolve
[[PromiseState]]: fulfilled
; - 调用 reject
[[PromiseState]]: rejected
; - 抛出 Error
throw Error
Promise 状态只能更改一次。
1
2
3
4
5new Promise((resolve, reject) => {
// 1 resolve('fulfilled')
// 2 reject('rejected')
throw 'error' // Promise {<rejected>: 'error'}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: "error"
})- 调用 resolve
Promise 的值 [[PromiseResult]]
保存着异步任务的结果,由 resolve, reject 修改或返回。
Promise 工作流
flowchart TB subgraph 等待状态Pending Pending("new Promise(excutor)") end subgraph 已完成状态 Fulfilled(Fulfilled
) Reject(Reject) end Pending --> async{异步处理} async --> |resolved 成功| Fulfilled["状态 Fulfilled, 返回 Promise 对象"] async -->|rejected 失败| Reject["状态 Reject, 返回 Promise 对象"] Fulfilled -->|".then(onResolved, onReject)"| onResolved['执行 onResolved 回调'] Reject --> |".then(..., onReject)
.catch(onRejction)"| onReject['执行 onReject 回调'] onResolved --> Promise["新的 Promise 对象"] onReject --> Promise
Promise API
Promise 构造函数
1 | /** |
Promise 实例方法
Promise.prototype.then()
1 | // 根据 PromiseState 调用不同状态的回调函数。 |
Promise.prototype.catch()
Promise.prototype.then
对于失败回调的单独封装
1 | Promise.prototype['catch'] = function (onRejected) { |
Promise.prototype.finally()
注册一个 promise 状态变化时必须执行的回调函数,无论状态成功还是失败。返回 Promise 对象,支持继续链式调用。
避免在 promise 的 then() 或 catch() 中处理相同的代码
Promise 静态方法
Promise.resolve()
Promise.resolve(params)
flowchart TB params["Promise.resolve(params)"] --> condition{"params instanceof Promise"} condition -->|yes| result1["参数的状态和结果决定了Promise.resolve('params')的状态和结果"] condition -->|no| result2["[[PromiseState]]:fulfilled,[[PromiseResult]]:params的值"]
1 | // value 为数据,返回 状态为 Fulfilled 状态的 Promise 对象 |
Uncaught (in promise) error
[[PromiseState]] : “rejected” ,状态必须被 Promise.catch 捕获
1 | // value 可以是数据也可以是 Promise 对象 |
Promise.reject()
Promise.reject(params)
快速返回失败 Promise 对象
1 | Promise.reject(Promise.resolve(123)) |
无论参数是什么类型,即使参数返回状态为 fulfilled 的 Promise,结果也是失败 rejected。
1 | Promise.reject = function (value) { |
Promise.all()
参数 promises,包含多个 promise 的数组
返回结果:promises 数组中,所有状态成功,返回数组,数组元素为每个 promise resolve 结果。失败返回结果则为 promises 数组中,第一个 reject 的结果
1 | Promise.all = function (arr) { |
1 | let p1 = new Promise((resolve, reject) => { |
Promise.race
参数为 Promise 数组,返回结果与状态为数组中第一个返回 Promise 的状态与值
1 | Promise.race = function (values) { |
1 | let p1 = new Promise((resolve, reject) => { |
Question
Q2 - Promise 能否执行多个回调
1 | let promise = new Promise((resolve, reject) => { |
flowchart TB promise --> state{调用 reject 改变状态} state --> |yes| then["then1:reject\nthen2:then reject"] state --> |no| pending["...[PromiseState]] : 'pending' ..."]
只要状态发生变化,可以通过
then
执行多个回调
Q3 - 改变 Promise 状态和指定回调函数谁先谁后
…???
Q4 - promise.then() 返回的 Promise 结果状态由什么决定
promise.then(onFulfilled, onRejected) 返回的 Promise 状态由 onFulfilled/onRejected 的返回值决定
- onFulfilled/onRejected 返回非 Promise,那么 then() 返回的 Promise 状态为 fulfilled
- onFulfilled/onRejected 抛出异常,那么 then() 返回的 Promise 状态为 rejected
- onFulfilled/onRejected 返回 Promise,那 then() 返回的 Promise 的状态和结果值为,回调函数中返回的 Promise 的状态和结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18let promise = new Promise((resolve, reject) => {
reject('error')
})
console.log(null,promise.then(null,v=>{
return undefined
})) // Promise {<pending>} [[Prototype]] : Promise [[PromiseState]] : "fulfilled" [[PromiseResult]] : undefined
console.log(null,promise.then(null,v=>{
throw 'then error'
})) // Promise {<pending>} [[Prototype]] : Promise [[PromiseState]] : "rejected" [[PromiseResult]] : "then error"
console.log(null,promise.then(null,v=>{
return Promise.reject('promise reject error')
})) // Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: "promise reject error"
console.log(null,promise.then(null,v=>{
return Promise.resolve('promise resolve')
})) // Promise {<pending>} [[Prototype]] : Promise [[PromiseState]] : "fulfilled" [[PromiseResult]] : "promise resolve"
Q5 - promise 如何串连多个操作任务
promise.then(onFulfilled, onRejected) 返回 Promise 可以链式调用 then(onFulfilled, onRejected),过程中可以通过修改 onFulfilled, onRejected 回调函数的返回值,从而改变 then 返回的 Promise 的状态和结果值
1 | let promise = new Promise((resolve, reject) => { |
Q6 - promise 异常传透
promise 链处理过程中,遇到异常或 reject,会跳过中间的 then 链,直接执行 catch 处理异常。
1 | let promise = new Promise((resolve, reject) => { |
Q7 - 关于中断 promise 链
1 | let promise = new Promise((resolve, reject) => { |
Promise.promisify
NodeJS 的函数风格转换为 Promise 方法,可以认为是一种语法粮。
Promisify 的源码解析
Promise 的拒绝
显式拒绝 —— 在一个 promise 的执行函数中调用传入的 reject 方法
隐式拒绝 —— 处理的一个 promise 的过程中招聘一个异常
Promise
解决采用 callback 机制产生的如回调地狱一样的潜在问题,允许采用近乎同步的逻辑写异步代码
async/await 异步编程的终级解决方案
JavaScript 的 async/await 实现,也离不开 Promise,async 用于申明一个方法是异步的,await 用于等待一个异步方法执行完成。await 只能出现在 async 函数中。
async 关键字
用于标记一个函数,该函数返回一个 promise 对象,promise 对象的结果由 async 函数执行的返回值决定。
async 如何处理它的返回值的
1 | async function fn() { |
async 函数返回的是一个 Promise 对象,async 会把 return 变量通过 Promise.resolve() 封装成 Promise 对象。可以用 then() 链处理 Promise 对象,进行测试。
1 | async function fn() { |
flowchart TB enter[async 函数返回值] --> condition{instanceof 返回值 === promise} condition -->|yes| PromiseResult[结果为 promise 的状态和值]
await
async 函数返回 Promise, await 可以用于等待 async 异步的完成,异步操作返回的都是 promise, await 按顺序执行。