详解Promise
1、什么是Promise(为什么要有Promise)
简单说:异步编程的一种解决方案,解决了地狱回调的问题。
回调地狱: 指的是在请求的时候往往要根据当前请求结果继续请求, 这个时候就会造成代码可读性差、维护性差、复用性差, 另外只能在回调之中处理异常。
由此,推出了promise这种异步编程的解决方案,在es6中被统一了用法,原生提供了promise对象。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
2、Promise的核心原理
promise的核心原理其实就是发布订阅模式,通过两个队列来缓存成功的回调(onResolve)和失败的回调(onReject)。在new Promise时需要传递一个executor执行器,执行器会立刻执行执行器中传递了两个参数:resolve成功的函数、reject失败的函数,他们调用时可以接受任何值的参数value。
promise状态
promise有3种状态(pending、resolved、rejected)
- pending(执行中)
- resolved(成功,又称Fulfilled)
- rejected(拒绝) 其中pending为初始状态,fulfilled和rejected为结束状态(结束状态表示promise的生命周期已结束), 从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型),然后执行相应缓存队列中的任务。
promise实例
- 每个实例都有一个then方法,这个方法传递两个参数,一个是成功回调onfulfilled,另一个是失败回调onrejected。
- promise实例调用then时,如果状态resolved,会让onfulfilled执行并且把成功的内容当作参数传递到函数中。
- promise中可以同一个实例then多次,如果状态是pengding 需要将函数存放起来, 等待状态确定后在依次将对应的函数执行(发布订阅)。
3、Promise的使用方法
resolve和reject
new Promise((resolve, reject) => { resolve(); reject(); })里面有多个resovle或者reject只执行第一个。如果第一个是resolve的话后面可以接.then查看成功消息。如果第一个是reject的话,.catch查看错误消息。
比如以下的嵌套请求:
new Promise(请求1)
.then(请求2(请求结果1))
.then(请求3(请求结果2))
.then(请求4(请求结果3))
.then(请求5(请求结果4))
.catch(处理异常(异常信息))
promise.all方法
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。示例代码如下:
let p1 = new Promise((resolve, reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promise.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败了,打出 '失败'
})
对上述代码的说明:
- 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
- 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
promise.race方法
Promise.race()方法同样是将多个Promise实例,包装成一个新的Promise实例。与Promise.all不同的是,多个Promise实例,只要有一个率先改变,race方法就跟着改变,并返回那个率先改变的Promise实例的返回值,传递给回调函数。比如有一个方法率先失败了那就返回整体的reject, 有一个方法率先成功了就返回整体的resolve。