Promise
Promise对象的特点:
- 对象的状态不受外界影响
- 状态一旦改变就不会再改变了。(状态只能改变一次)
Promise的三种状态: 保存在 [[PromiseState]]
- pending:进行中
- fulfilled:成功,当调用resolve时,状态会从pending变为fulfilled
- rejected:失败,当调用reject时,状态会从pending变为rejected
Promise的基本用法
new Promise
- 创建一个Promise对象
const p = new Promise((resolve, reject) => {
resolve('aaa')
})
console.log(p) // [[Prototype]]: Promise
// [[PromiseState]]: "fulfilled" 调用resolve结果为fulfilled,调用reject结果为rejected
// [[PromiseResult]]: "aaa" 这里的值取决与resolve或者reject的参数
- 状态只能改变一次,如果调用了resolve之后又调用了reject,那么reject会被忽略,反之亦然。
const p = new Promise((resolve, reject) => {
resolve('resolve')
reject('reject') // 这个函数调用会被忽略
// 这里后面的其他代码还是正常运行
})
console.log(p) /**[[Prototype]]: Promise
*[[PromiseState]]: "fulfilled"
*[[PromiseResult]]: "aaa"
**/
Promise.prototype.then方法
- Promise的状态改变时,会回调then方法的参数
- 该方法接收两个函数参数,当Promise的状态从pending变为fulfilled时,会回调第一个参数,当Promise的状态从pending变为rejected时,会回调第二个参数。
const p = new Promise((resolve, reject) => {
resolve('aaa')
})
const p1 = p.then((res) => {
// 如果p的状态为fulfilled,会执行该函数,并且resolve的参数会传递给res
console.log(res) // 'aaa'
}, (err) => {
// 如果p的状态为rejected,会执行该函数,并且rejected的参数会传递给err
})
- Promise.prototype.then方法会返回一个新的Promise对象
const p = new Promise((resolve, reject) => {
})
const p1 = p.then((res) => {
}, (err) => {
})
console.log(p1) /** [[Prototype]]: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
*/
- Promise.prototype.then方法返回的对象中 [[PromiseState]] [[PromiseResult]] 这两个值是取决与哪里的呢?
// 情况一
// p的状态为pending,[[PromiseState]]: "pending",[[PromiseResult]]: undefined
const p = new Promise((resolve, reject) => {
// 这里没有调用resolve或者reject改变p的状态
})
const p1 = p.then((res) => {
// 由于p的状态没有发生改变,这个回调函数不会被执行
}, (err) => {
// 由于p的状态没有发生改变,这个回调函数不会被执行
})
console.log(p1) /** [[Prototype]]: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
*/
// 情况二
// p的状态不为pending,p.then的参数没有返回值,[[PromiseState]]: "fulfilled",[[PromiseResult]]: undefined
const p = new Promise((resolve, reject) => {
resolve('aaa') // 只要p的状态不为pending,无论是fulfilled还是rejected,最终[[PromiseState]]都是fulfilled
})
const p1 = p.then((res) => {
console.log(res) // 'aaa'
// 注意:这个函数没有返回值,或者说返回值为undefined
}, (err) => {
console.log(err)
})
console.log(p1) /** [[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
*/
// 情况三
// p的状态不为pending,p.then的参数有返回值
const p = new Promise((resolve, reject) => {
resolve('aaa') // 只要p的状态不为pending,无论是fulfilled还是rejected,最终[[PromiseState]]都是fulfilled
})
const p1 = p.then((res) => {
console.log(res) // 'aaa'
return res // p1的[[PromiseResult]]取值取决于这里返回的值
// 注意:这个函数返回了res
}, (err) => {
console.log(err)
})
console.log(p1) /** [[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "aaa"
*/
// 情况四
// p的状态不为pending,p.then的参数返回值为Promise
const p = new Promise((resolve, reject) => {
resolve('aaa')
})
const p1 = p.then((res) => {
console.log(res) // 'aaa'
return new Promise((resolve, reject) => {
resolve('aaa')
}) // p1的[[PromiseResult]]和[[PromiseState]]的取值,完全取决于这个Promise
}, (err) => {
console.log(err)
})
console.log(p1) /** [[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "aaa"
*/
// 情况五
// p的状态不为pending,p.then没有传递参数
// 这个时候p1的结果和p的结果是一样的,但是这两个对象不是同一个对象
const p = new Promise((resolve, reject) => {
resolve('aaa') // 只要p的状态不为pending,无论是fulfilled还是rejected,最终[[PromiseState]]都是fulfilled
})
const p1 = p.then() // 这里没有传递参数
console.log(p1) /** [[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "aaa"
*/
-
总结Promise.then返回的Promise对象的属性
- 在Promise.prototype.then有传函数参数的情况下,只要该函数参数被调用了(无论是第一个函数参数,还是第二个函数参数) ,就相当于在Promise中调用了resolve方法,这个时候Promise.prototype.then返回的Promise对象的 [[PromiseState]] 属性就会变成fulfilled(也就是说Promise的状态从pending变成了fulfilled) ,而 [[PromiseResult]] 的值取决于被调用的函数的返回值
- 在Promise.prototype.then有传函数参数的情况下,该函数参数被调用并且该函数参数的返回值是一个Promise对象,那么Promise.then返回的对象的状态和属性取决于函数参数返回的那个Promise对象
- 在Promise.prototype.then没有传参数的情况下,返回的Promise对象和调用.then的Promise对象的属性完全一致,但是这两个对象不是同一个对象
Promise.prototype.catch方法
-
该方法接收一个函数参数,返回一个Promise对象
- 当Promise的状态从pending变为rejected时,会回调该方法的参数
const p = new Promise((resolve, reject) => {
reject('reject')
})
const p1 = p.catch((err) => {
console.log(err)
})
console.log(p1) /*
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled" 只要catch的参数被回调那么这里就是fulfilled
[[PromiseResult]]: undefined 这里的取值取决于catch的返回值
**/
- 当Promise的状态从pending变为fulfilled时,不会回调该方法的参数,不过返回的Promise对象和调用.catch的Promise对象属性完全一样,但是这两个对象不是同一个对象
const p = new Promise((resolve, reject) => {
resolve('aaa')
})
const p1 = p.catch((err) => {
console.log(err) // 这里的代码不会被调用
})
console.log(p1) /*
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: aaa
**/
- 当Promise.prototype.catch方法没有传递参数时,和Promise.then没有传递参数的效果类似,返回的Promise对象和调用.catch的Promise对象属性完全一样,但是这两个对象不是同一个对象
Promise出现代码错误时
- new Promise时传入的函数体出现代码错误时
// 情况一
// 在执行报错代码时,Promise的状态是pending
const p = new Promise((resolve, reject) =>{
console.log(aaa) // 这里的aaa是未定义的,不会输出该语句,并且该语句后面的所有语句都不会执行
// 当这里的代码报错时,会自动调用reject函数,并且把报错信息作为reject函数的参数
})
const p1 = p.then((res) => {
}, (err) => {
// 这里就可以接受到报错的信息
})
const p2 = p.catch(err => {
// 这里也可以接受到报错的信息
})
// 情况二
// 在执行报错代码时,Promise的状态已经不是pending
const p = new Promise((resolve, reject) =>{
resolve('resolve')
console.log(aaa) // 这里的aaa是未定义的,不会输出该语句,并且该语句后面的所有语句都不会执行
// 由于Promise的状态只能被改变一次,所以在这种情况下,报错代码和报错代码后的代码类似于被吃掉了
})
const p1 = p.then((res) => {
}, (err) => {
})
const p2 = p.catch(err => {
})
Promise.prototype.catch和Promise.prototype.then的第二个回调有什么区别?
- 这两个方法都是当Promise的状态变为rejected时,会回调的方法,本质上没有什么太大的区别
- 不过开发中,推荐使用catch方法,而不是Promise.then的第二个回调。
const p = new Promise((resolve, reject) =>{
}).then(res => {
// 如果这里代码出错
}, err =>{
}).catch(err =>{
// 这里能捕获到
})
Promise.resolve方法(该方法是Promise类的方法)
- 生成一个Promise对象,该对象的状态为fulfilled,结果为传入的参数
Promise.resolve('aaa')/*
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: aaa
**/
Promise.reject方法(该方法是Promise类的方法)
- 生成一个Promise对象,该对象的状态为rejected,结果为传入的参数
Promise.reject('aaa')/*
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: aaa
**/
Promise.all方法(该方法是Promise类的方法)
- Promise.all方法用于将多个Promise实例包装成一个新的Promise实例
- 该方法接收一个数组(可以不是数组,但是必须有iterator接口) 作为参数,并且该数组的每一项必须都是Promise实例,如果不是就会调用Promise.resolve将该项转变为Promise实例
- Promise.all返回的Promise对象的状态和result取决于传入的promise实例参数
// 情况一
// 传入的promise实例状态都是pending
const p1 = new Promise((resolve, reject) => {
})
const p2 = new Promise((resolve, reject) => {
})
const p3 = new Promise((resolve, reject) => {
})
const p = Promise.all([p1, p2, p3])
console.log(p) /*
[[Prototype]]: Promise
[[PromiseState]]: "pending"
[[PromiseResult]]: undefined
**/
// 情况二
// 传入的Promise实例状态都是fulfilled
const p1 = new Promise((resolve, reject) => {
resolve('aaa')
})
const p2 = new Promise((resolve, reject) => {
resolve('bbb')
})
const p3 = new Promise((resolve, reject) => {
resolve('ccc')
})
const p = Promise.all([p1, p2, p3])
console.log(p) /*
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: ['aaa', 'bbb', 'ccc']
**/
// 情况三
// 传入的Promise实例状态都是rejected
const p1 = new Promise((resolve, reject) => {
reject('aaa')
})
const p2 = new Promise((resolve, reject) => {
reject('bbb')
})
const p3 = new Promise((resolve, reject) => {
reject('ccc')
})
const p = Promise.all([p1, p2, p3])
console.log(p) /*
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: 'aaa'
**/
// 情况四
// 传入的promise实例状态包含pending,fulfilled,rejected
const p1 = new Promise((resolve, reject) => {
})
const p2 = new Promise((resolve, reject) => {
resolve('bbb')
})
const p3 = new Promise((resolve, reject) => {
reject('ccc')
})
const p = Promise.all([p1, p2, p3])
console.log(p) /*
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: 'ccc'
**/
-
总结Promise.all返回的Promise对象的状态和result
- 当传入的实例中,只要有一个状态为rejected,那么返回的Promise实例就和这个状态为rejected的实例的结果一样
- 当传入的实例中,有多个状态为rejected的,那么返回的Promise实例会和第一个状态为rejected的实例的结果一样
- 当传入的实例中,全部实例状态都为fulfilled,那么返回的Promise实例的状态为fulfilled,result为一个数组,该数组的第一项是第一个状态为fulfilled的实例的result,以此类推
- 当传入的实例中,没有状态为rejected,但是实例的状态既包含pending,又包含fulfilled,或者实例的状态都是pending,那么返回的Promise实例的状态为pending,result为undefined
-
Promise.all方法一般用于需要等到多个请求同时请求成功的时候使用
Promise.race方法
- Promise.race使用方法基本和Promise.all一样
- 该方法传入的Promise实例中,只要有一个率先改变状态,那么Promise.race返回的Promise对象的状态和result就和率先改变状态的那个promise实例一致
- Promise.race方法一般用于发送多个请求,只要有一个请求成功就使用该请求的数据
\