-
Promise的理解和应用
promise是什么
理解
- 抽象表达
- promise是一门新的技术(ES6规范)
- promise是js中进行异步编程的新解决方案(旧方案是单纯使用回调函数)
- 具体表达
- 实例对象的一个属性PromiseState
1. pending 未决定的 2. resolved/fullfillled 成功 3. rejected 失败
- promise对象的状态只改变一次
promise对象的值
- 实例对象中的另一个属性PromiseResult
- 保存着异步任务成功/失败的结果
- 无论变为成功还是失败 , 都会有一个结果数据
- 成功的结果数据一般称为 value, 失败的结果数据一般称为 失败的结果数据一般称为 reason
promise的基本流程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26<script>
// 1) 创建promise对象(pending状态), 指定执行器函数
const p = new Promise((resolve, reject) => {
// 2) 在执行器函数中启动异步任务
setTimeout(() => {
const time = Date.now()
// 3) 根据结果做不同处理
if (time % 2 === 1) {
resolve('成功的值 ' + time)
} else {
reject('失败的值' + time)
}
}, 2000)})
p.then(
value => {
console.log('成功的value: ', value)
},
reason => {
console.log('失败的reason: ', reason)
}
)
</script>
为什么要用promise
支持链式调用,可以解决回调地狱问题
- 什么是回调地狱
- 回调函数嵌套调用,外部回调函数异步执行的结果 是嵌套的回调执行的条件
- 回调地狱的缺点
- 不便于阅读
- 不便于异常处理
- 解决方案
promise链式调用 - 终极解决方案
async/await
如何使用promise
API
Promise构造函数 : Promise (excutor) {}
- executor(执行器)函数 : 把promise对象的参数叫做执行器函数: (resolve, reject) => {}
- 执行器函数会在promise内部立即同步调用,then方法是异步调用的
- resolve函数 : 内部定义成功时我们调用的函数 value => {}
- reject函数 : 内部定义失败时我们调用的函数 reason => {}
- executor(执行器)函数 : 把promise对象的参数叫做执行器函数: (resolve, reject) => {}
Promise.prototype.then方法 : (onResolved, onRejected) => {}
- onResolved函数 : 成功的回调函数 (value) => {}
- onRejected函数 : 失败的回调函数 (reason) => {}
- 说明:指定用于得到成功value的成功回调和用于失败reason的失败回调返回一个新的promise对象
Promise.prototype.catch方法 : (onRejected) => {}
- onRejected函数 : 失败的回调函数 (reason) => {}
- 说明:then方法的语法糖,相当于 相当于 : then(undefined, onRejected)
Promise.resolve方法 : (value) => {}
- value:成功的数据或 promise对象
- 说明 :返回一个成功 /失败的 promise对象
Promise.reject方法 : (reason) => {}
- reason: 失败的原因
- 说明 : 返回一个失败的 promise对象
Promise.all方法 : (promises) => {}
- promises: 包含 n个 promise的数组 的数组
- 说明 : 返回一个新的promise,只有所有的promise都成功才成功,只要有一个失败了就直接失败
Promise.race方法 : (promises) => {}
- promises: 包含 n个 promise的数组 的数组
- 说明 : 返回一个新的 promise, 第一个完成的promise的结果状态就是最终的结果状态
promisify函数
- 可以将一般的回调函数转化成返回promise对象的函数
promise的几个关键问题
如何改变promise的状态
- resolve(value): 如果当前是 pending就会变为 resolved
- reject(reason): 如果当前是 pending就会变为 rejected
- 抛出异常 : 如果当前是 pending就会变为 rejected
一个promise对象指定多个成功/失败的回调函数,都会调用吗
- 当promise的状态改变为相应状态时都会调用
改变promise状态和指定回调函数谁先谁后
- 都有可能,正常情况下时先指定回调再改变状态,但也可以先改变状态再指定回调
- 如何先改变状态在指定回调
- 在执行器函数直接调用resolve/reject(同步任务)
- 延迟更长时间才调用then(比执行器函数时间长)
- 如何先指定回调再改变状态
- 执行器函数是异步任务,在异步回调函数中调用resolve/reject的时候,这时候先指定回调,后改变状态
- 什么时候才能拿到数据
- 如果是先改变的状态,当指定回调函数的时候,回调函数就会调用,从而得到数据
- 如果是先指定的回调(先指定不是先调用),当状态发生改变后,再调用回调函数时,才能得到数据
promise.then()返回的新promise的结果状态由什么决定
- 简单表达:由then()指定的回调函数执行的结果绝定
- 详细表达:
- 如果抛出异常,新promise变为rejected,reason为抛出的异常
- 如果返回的是非promise的任意值,新promise变为resolved,value为返回的值
- 如果返回的是另一个新promise,此promise的结果就会成为新promise的结果
promise如何串联多个操作任务
- promise的then返回一个新的promise,可以看成then()的链式调用
- 通过then的链式调用串联多个异步或同步任务
promise异常穿透
- 当使用promise的then链式调用时,可以在最后指定失败的回调
- 当前面的操作出现任何异常,都会直接传到最后失败的回调中处理
中断promise链
- 当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
- 办法:在回调函数中返回一个pendding状态的promise对象return new Promise(()=>{})
async和await
async函数
- 函数的返回值为promise对象
- promise对象的结果由async函数执行的返回值绝定
await表达式
- await右侧的表达式一般为promise对象,但也可以是其他值
- 如果表达式是promise对象,await返回的是promise成功的值
- 如果表达式是其他值,直接将此值作为await的返回值
- await必须写在async函数中,但async函数中可以没有await
- 如果await的promise失败,就会抛出异常,需要通过try catch捕获处理