Promise的基本使用

124 阅读5分钟

前言

在工作中虽然使用了很久的Promise,但是里面的一些细节还是有些迷糊,特写一篇博客来记录Promise的使用细节。

Promise 的三种状态

  • pedding:初始化状态
  • fulfilled:成功时状态
  • rejected: 失败时状态 需要注意的是,Promise是不可逆的,只能由peddingfulfilled或者由peddingrejucted

Promise resolve参数

Promiseresolve传递的参数分为三种情况

  • 一个普通的值或者对象,那么这个值或者参数就作为then回调的参数
const promise = new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
    console.log(res)  // 123
},err => {
    console.log(err) 
})
  • 一个新的Promise,那么这个新的Promise的状态会决定原来Promise的状态
// 新的Promise调用resolve
const p1 = new Promise((resolve,reject) => {
    resolve(new Promise((resolve,reject) => {
        resolve(123456)  
    }))
}).then(res => {
    console.log(res)  // 123456
},err => {
    console.log(err) 
})

// 新的Promise调用reject
const p2 = new Promise((resolve,reject) => {
    resolve(new Promise((resolve,reject) => {
        reject(123456)  
    }))
}).then(res => {
    console.log(res)  
},err => {
    console.log(err) // 123456
})
  • 一个实现了then方法的对象,那么这个对象称为thenable对象,会自动执行这个then方法,根据then方法的结果来决定原来Promise的状态
// thenable对象调用resolve
const p1 = new Promise((resolve,reject) => {
    resolve({
        then(resolve,reject){
            resolve(123456)
        }
    })
}).then(res => {
    console.log(res)  // 123456
},err => {
    console.log(err) 
})

// thenable对象调用reject
const p2 = new Promise((resolve,reject) => {
    resolve({
        then(resolve,reject){
            reject(123456)
        }
    })
}).then(res => {
    console.log(res)  
},err => {
    console.log(err) // 123456
})

then方法返回值

和上面resolve的参数一样,then方法也会返回三种类型的值:

  • 普通的值或者对象,将作为下一个then回调的参数
new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
     return 456
}).then(res => {
    console.log(res) // 456
})
  • 一个新的Promise,那么这个新的Promise的状态将会决定下一次回调的是then还是catch
new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
    return new Promise((resolve,reject) => {
        resolve(456)
    })
}).then(res => {
    console.log(res)  // 456
})

new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
    return new Promise((resolve,reject) => {
        reject(456)
    })
}).catch(err => {
    console.log(err)  // 456
})
  • 一个thenable对象,thenable对象的状态决定下一次回到的是then还是catch
new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
    return ({
        then(resolve,reject){
            resolve(456)
        }
    })
}).then(res => {
    console.log(res)  //456
})

new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
    return ({
        then(resolve,reject){
            reject(456)
        }
    })
}).catch(err => {
    console.log(err)  //456
})

注意:当then抛出异常的时候,状态将会变成rejected

new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
    throw new Error("抛出异常")
}).catch(err => {
    console.log(err) // Error: 抛出异常
})

catch方法返回值

then返回的返回值一样,有三种情况

  • 返回一个普通的值或者对象,将作为下一个then回调的参数
  • 返回一个新的Promise,根据返回的Promise的状态来决定
  • 返回一个thenable对象,根据thenable对象的状态来决定 如果抛出异常,则下一次还是catch回调

finally方法

finally是ES9中新增的一个方法,无论Promise的状态是fulfilled还是rejected,最终都会被执行,此方法不需要接受参数

new Promise((resolve,reject) => {
    resolve(123)
}).then(res => {
    console.log(res)  // 123
    return new Promise((resolve,reject) => {
        reject(456)
    })
}).catch(err => {
    console.log(err)  // 456
}).finally(() => {
    console.log("finall执行")
})

上面的then catch finally 属于Promise的实例方法,存放于Promiseprototype上,下面来看一下Promise的类方法

Promise.resolve()

相当于new Promise,并调用了resolve方法,接收的参数同上面一样,这里不过多赘述,并将Promise的状态改为fulfilled

Promise.resolve(123).then(res => {
    console.log(res) // 123
})

Promise.reject()

reject方法类似于resolve,只是将Promise的状态转换为rejected

Promise.reject(123).catch(err => {
    console.log(err)  // 123
})

Promise.reject无论传递什么参数,都会作为catch回调的参数

Promise.reject(new Promise((resolve,reject) => {
    resolve(123)
})).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err) // Promise {123}
})

Promise.all()

它的作用是将多个Promise包裹在一起,形成一个新的Promise,新的Promise将由包裹的所有的Promise决定

  • 当所有的Promise都是fulfilled时,新的Promise的状态就是fulfilled,并且会将所有Promise的结果放在一个数组中
  • 一旦有一个Promise的状态为rejected,不会继续执行其他的Promise,新的Promise的状态就是rejected,并且返回第一个状态为rejectedPromise的结果
const p1 = Promise.resolve(123)
const p2 = Promise.resolve(456)
const p3 = Promise.resolve(789)
Promise.all([p1,p2,p3]).then(res => {
    console.log(res)  // [123,465,789]
})

const p4 = Promise.reject('reject')
Promise.all([p1,p2,p3,p4]).catch(err => {
    console.log(err) // reject
})

Promise.allSettled()

Promise.all()方法有一个缺陷,当有一个Promise的状态为rejected时,新的Promise会立马变成rejected状态,对于处于fulfilledPromise是拿不到结果的

  • ES11中新增了Promise.allSettled()方法,该方法会等到所有包裹的Promise都有结果,无论包裹的Promise的结果是fulfilled还是rejected,才会有最终的形态
  • 新的Promise的状态是fulfilled
const p1 = Promise.resolve(123)
const p2 = Promise.resolve(456)
const p3 = Promise.resolve(789)
Promise.allSettled([p1,p2,p3]).then(res => {
    console.log(res)  /* [
                          { status: 'fulfilled', value: 123 },
                          { status: 'fulfilled', value: 456 },
                          { status: 'fulfilled', value: 789 }
                        ]*/
})

const p4 = Promise.reject('reject')
Promise.allSettled([p1,p2,p3,p4]).then(res => {
    console.log(res)  /* [
                          { status: 'fulfilled', value: 123 },
                          { status: 'fulfilled', value: 456 },
                          { status: 'fulfilled', value: 789 },
                          { status: 'rejected', reason: 'reject' }
                        ]*/
})

Promise.race()

race有竞赛的意思,表示多个Promise竞争,谁先有结果,就返回谁

cosnt p1 = Promise.resolve('resolve')
const p2 = Promise.reject('reject')
Promise.race([p1,p2]).then(res => {
    console.log(res) // resolve
})

Promise.race([p2,p1])。catch(err => {
    console.log(err)  // reject
})

Promise.any()

Promise.any()是ES12中新增的方法,和race()方法类似

  • any()方法会等到一个fulfilled状态,来决定新Promise的状态,并返回第一个fulfilled状态的结果
  • 若所有的Promise都是rejected,则返回一个AggregateError错误,可以在err.errors里面查看详情
const p1 = Promise.resolve(123)
const p2 = Promise.resolve(456)
const p3 = Promise.reject('reject1')
const p4 = Promise.reject('reject2')

Promise.any([p1,p2,p3,p4]).then(res => {
    console.log(res) // 123
})

Promise.any([p3,p4,p1,p2]).then(res => {
    console.log(res) // 123
})

Promise.any([p3,p4]).catch(err => {
    console.log(err)  // [AggregateError: All promises were rejected]
    console.log(err.errors) // [ 'reject1', 'reject2' ]
})