不了解Promise?不知道怎么使用Promise?不知道Promise的状态改变和[[PromiseResult]]的取值?看这篇就够了。

1,170 阅读8分钟

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实例的状态为fulfilledresult为一个数组该数组的第一项是第一个状态为fulfilled的实例的result,以此类推
    • 当传入的实例中,没有状态为rejected,但是实例的状态既包含pending,又包含fulfilled或者实例的状态都是pending,那么返回的Promise实例的状态为pendingresult为undefined
  • Promise.all方法一般用于需要等到多个请求同时请求成功的时候使用

Promise.race方法
  • Promise.race使用方法基本和Promise.all一样
  • 该方法传入的Promise实例中只要有一个率先改变状态,那么Promise.race返回的Promise对象的状态和result就和率先改变状态的那个promise实例一致
  • Promise.race方法一般用于发送多个请求,只要有一个请求成功就使用该请求的数据

\