Promise
Promise的状态
实例对象的一个内置属性PromiseState
pending 悬而未决的
变为resolved 成功的
pending
变为rejected 失败的
说明:只有这2种,且一个promise对象只能改变一次无论变为成功还是失败,都会有一个结果数据成功的结果数据一般称为value,失败的结果数据一般称为reason
Promise 对象的值
实例对象中的一个属性 PromiseResult
保存着异步任务成功/失败的结果
resolve(result)
reject(result)
Promise的基本流程
API
Ⅰ- Promise 构造函数: Promise (excutor) {}
(1) executor 函数: 执行器 (resolve, reject) => {} 函数类型的参数
(2) resolve 函数: 内部定义成功时我们调用的函数 value => {}
(3) reject 函数: 内部定义失败时我们调用的函数 reason => {}
说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行,换话说Promise支持同步也支持异步操作
1 | let p = new Promise((resolve,reject)=>{ |
Ⅱ-Promise.prototype.then 方法: (onResolved, onRejected) => {}
(1) onResolved 函数: 成功的回调函数 (value) => {}
(2) onRejected 函数: 失败的回调函数 (reason) => {}
说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调 返回一个新的 promise 对象
Ⅲ-Promise.prototype.catch 方法: (onRejected) => {}
(1) onRejected 函数: 失败的回调函数 (reason) => {}
说明: then()的语法糖, 相当于: then(undefined, onRejected)
(2) 异常穿透使用:当运行到最后,没被处理的所有异常错误都会进入这个方法的回调函数中
Ⅳ-Promise.resolve 方法: (value) => {}
不属于实例对象,属于函数对象 快速返回一个成功的promise对象
(1) value: 成功的数据或 promise 对象
说明: 返回一个成功/失败的 promise 对象,直接改变promise状态
- 如果传入的参数为非Promise类型的对象,则返回的结果为成功的Promise对象
- 如果传入的参数为Promise对象,则参数的结果决定了resolve的结果
1
2
3
4
5
6
7
8
9
10let p1 = Promise.resolve(999);
console.log(p1)
let p2 = Promise.resolve(new Promise((resolve, reject)=>{
// resolve('ok') resolve和reject同时写的话,只会调用最前面的一个
reject('error') // 参数的状态决定了p2的状态
}))
p2.catch(reason => {
console.log(reason)
})
console.log(p2);
Ⅴ-Promise.reject 方法: (reason) => {}
不属于实例对象,属于函数对象 快速返回一个失败的promise对象
(1) reason: 失败的原因
说明: 返回一个失败的 promise 对象,直接改变promise状态,状态永远都是失败的
1 | let p1 = Promise.reject(999); |
Ⅵ-Promise.all 方法: (promises) => {}
promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败
成功的结果是所有成功的promise组成的结果,失败的结果是失败的promise组成的结果
1 | let p1 = new Promise((resolve, reject) => { resolve('成功'); }) |
只要任何一个输入的 promise 的 reject 回调执行或者输入不合法的 promise 就会立即抛出错误,并且 reject 的是第一个抛出的错误信息。
Ⅶ-Promise.race 方法: (promises) => {}
(1) promises: 包含 n 个 promise 的数组
说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。
如p1延时,开启了异步,内部正常是同步进行,所以p2>p3>p1,结果是P2
1 | const promise1 = new Promise((resolve, reject) => { |
Promise的几个关键问题
Ⅰ-如何改变 promise 的状态?
(1) resolve(value): 如果当前是 pending 就会变为 resolved
(2) reject(reason): 如果当前是 pending 就会变为 rejected
(3) 抛出异常: 如果当前是 pending 就会变为 rejected
Ⅱ-一个 promise 指定多个成功/失败回调函数, 都会调用吗?
当 promise 改变为对应状态时都会调用,改变状态后,多个回调函数都会调用,并不会自动停止
如果状态是pending
且没有发生改变时,则回调函数不会调用
1 | let p = new Promise((resolve, reject) => { resolve('OK');}); |
Ⅲ- 改变 promise 状态和指定回调函数谁先谁后?
(1) 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
先指定回调再改变状态(异步):先指定回调–> 再改变状态 –>改变状态后才进入异步队列执行回调函数
先改状态再指定回调(同步):改变状态 –>指定回调 并马上执行回调
(2) 如何先改状态再指定回调? –>注意:指定并不是执行
① 在执行器中直接调用 resolve()/reject() –>即,不使用定时器等方法,执行器内直接同步操作
② 延迟更长时间才调用 then() –>即,在.then()这个方法外再包一层例如延时器这种方法
(3) 什么时候才能得到数据? 即 回调函数什么时候执行
① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
1 | let p = new Promise((resolve, reject) => { |
Ⅳ-promise.then()返回的新 promise 的结果状态由什么决定?
(1) 简单表达: 由 then()指定的回调函数执行的结果决定
(2) 详细表达:
① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
1 | let p = new Promise((resolve, reject) => { |
Ⅴ- promise 如何串连多个操作任务?
(1) promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务,这样就能用then()将多个同步或异步操作串联成一个同步队列
1 | let p = new Promise((resolve, reject) => { |
Ⅵ-promise 异常传透
- 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调
- 前面任何操作出了异常, 都会传到最后失败的回调中处理
- 注:可以在每个then()的第二个回调函数中进行err处理,也可以利用异常穿透特性,到最后用
catch
去承接统一处理,两者一起用时,前者会生效(因为err已经将其处理,就不会再往下穿透)而走不到后面的catch1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21getJSON('./hong.json')
.then(function (posts) {
throw new Error('抛出异常')
})
.then(res => console.log(res), e => console.log('被then的错误回调捕获', e))
.catch(function (error) {
// 处理 getJSON 和 前一个回调函数运行时发生的错误
console.log('错误捕获: ', error);
});
//执行结果: 被then的错误回调捕获 Error: 抛出异常
/******************** 利用异常穿透 ****************************************/
getJSON('./hong.json')
.then(function (posts) {
throw new Error('抛出异常')
})
.then(res => console.log(res)) //此处差异,不指定 reject 回调,利用异常穿透传到最后
.catch(function (error) {
console.log('错误捕获: ', error);
});
//执行结果: 错误捕获: Error: 抛出异常
Ⅶ- 中断 promise 链?
在关键问题2中,可以得知,当promise状态改变时,他的链式调用都会生效,那如果我们有这个一个实际需求:我们有5个then(),但其中有条件判断,如当我符合或者不符合第三个then条件时,要直接中断链式调用,不再走下面的then,该如何?
(1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
(2) 办法: 在回调函数中返回一个 pendding 状态的promise 对象 那么因为状态是pending,所以then就不会继续被调用了,实现了promise链的中断
1 | let p = new Promise((resolve, reject) => { |
手写Promise
疑点
1 | const promise1 = new Promise((resolve, reject) => { |
为什么result
的值为空
1 | function foo() { |