Promise定义
Promise
对象用来解决异步问题
以前是使用回调函数和事件处理来解决异步问题,ES6中几乎可以覆盖所有的异步场景。
ES6中增强的功能,ES为了兼容以前的版本,以前旧的写法并没有抛弃,针对这些场景推出了新的API,这套API对异步的处理,变得更为简洁。
Promise
对象,可以获取异步操作的消息,提供统一的API,几乎所有的异步场景都可以用同样的方法进行处理。
发生异步操作的阶段
ES6将某一件事情可以发生异步操作时,分为了两个阶段
unsettled
未决阶段 和settled
已决阶段。
事情总是从未决阶段逐步发展到已决阶段,同时,未决阶段有控制通往已决阶段的能力
未决阶段有权利决定事情的走向,未决阶段可以决定事情走向最终的状态
Promise对象代表一个异步操作,分为三个状态:
-
pending:挂起(等待) 处于未决阶段,表示事情处于挂起,最终结果没有出来
-
resolved:已处理
处于已决阶段,表示整个事情已经出现结果,并且可以按照正常的逻辑进行下去的结果 -
rejected:已拒绝
处于已决阶段,表示整个事情已经出现结果,并且是一个无法按照正常逻辑进行下去的结果这三个阶段,不管到达了哪个阶段还是哪个状态,都是不可以逆,当事情已经到达 已决阶段后,通常要进行后续的处理,不同的已决解决,决定了不同的后续处理, 同时,后续的处理可能会有多个,因此会形成任务队列,这些后续处理会按照顺 序,当达到对应的状态后依次执行
通过调用
resolve
函数将Promise
对象推向已决阶段的resolved
状态
调用reject
函数将Promise
推向已决阶段的rejected
状态
注意:resolve
和reject
只能使用一个,如果使用了多个,也只有第一个才有效 传递参数只能为一个,表示推向状态的数据
用法
在ES6中,Promise
对象是一个构造函数,它的两个参数是两个回调函数,分别是resolve
和reject
,分别代表请求成功状态和请求失败状态。
const pro = new Promise(function(resolve, reject){
setTimeout( () => {
if(Math.random() < 0.9){
resolve('通过');
} else{
resolve('拒绝');
}
},100)
})
pro.then(data => { //请求成功推送的状态then()
console.log('通过resolve推过来的状态')
console.log(data)
},err => {
console.log("通过reject推过来的状态")
console.log(err)
})
catch()
注册一个后续处理函数,当promise
为rejected
状态是运行该函数,将失败写在catch
中
pro.then(data => {
console.log(data)
}).catch(data => {
console.log(data)
})
Promise.all()方法
Promise.all()
方法会返回一个新的promise
对象,如果里面所有的promise
对象都成功才会触发,一旦有一个失败,则该promise
对象为失败。
作为参数的 Promise
, catch
方法推向了rejected
状态,就会触发catch
方法
const prom = new Promise((resolve, reject) => {
resolve('通过');
})
.then(data => data)
.catch(err => err);
const pro = new Promise((resolve, reject) => {
throw ('错误');
})
.then(data => data)
.catch(err => err);
Promise.all([prom, pro]).then(data => console.log(data))
.catch(err => console.log(err))
//["通过", "错误"]
Promise.race()方法
Promise.race()
方法当参数中的任意一个promise
对象完成时候,就马上回去使用完成的这个promise
对象的结果,不管这个结果成功还是失败
const prom = new Promise((resolve, reject) => {
resolve('通过');
})
.then(data => data)
.catch(err => err);
const pro = new Promise((resolve, reject) => {
throw ('错误');
})
.then(data => data)
.catch(err => err);
Promise.race([prom, pro]).then(data => console.log(data))
.catch(err => console.log(err))
//通过
Promise
对象的缺点
- 新建后就会立即执行,中途无法在取消
const pro = new Promise(function(resolve, reject){
console.log('Promise');
resolve();
})
pro.then(() => {
console.log('resolved');
})
console.log('yaya');
//Promise
//yaya
//resolved
上例中,先输出的是Promise
,是因为Promise
新建后立即执行,resolved
之所以会在最后输出,之后then
方法所指的回调函数,将当前脚本的所有任务执行完才会执行
- 当不设置回调函数时,
Promise
内部会抛出错误,不会反应到外部
当其处于pending
状态时,就不能知道当前发展到什么阶段
面试重点
- 未决阶段的处理函数是同步的,会立即执行
resolved
是一个正常的已决状态,后续处理表示为thenable
rejected
是一个非正常的已决状态,后续处理表示为catchable
thenable
和catchable
函数为异步,就算会立即执行,也要先加入等待队列中,加入微队列then
可以只添加thenable
函数,catch
可以单独添加catchable
函数
const pro = new Promise((resolve,reject) => {
throw new Error("123")
})
pro.then(data => {
console.log(data)
})
pro.catch(err => {
console.log(err)
})
- 在未决阶段的处理函数中,如果发生为捕获的错误,就会将当前状态推向
rejected
,而且还会被catchable
捕获
一旦推向了已决阶段,就没办法再去做任何的改变
const pro = new Promise((resolve,reject) => {
throw new Error("错误") //未捕获
try {
throw new Error("123") //捕获了的错误
} catch(e) {
}
resolve(1432);
reject(3345);
})
pro.then(data => {
console.log(data)
})
pro.catch(err => {
console.log(err)
})
- 如果当前的
promise
是未决的,得到的新的promise
是挂起状态
const pro = new Promise((resolve, reject) => {
resolve('123'); //Promise {<resolved>: "123"} resolve ==> resolved状态
})
console.log(pro);
const promise = pro.then(result => result * 2) //通过then调用以后,又是返回的一个全新promise对象
console.log(promise); //Promise {<pending>} pengding状态 等待前面的处理结果