Promise 详解

147 阅读3分钟

highlight: an-old-hope

一、概述

Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件。

二、Promise 的三种状态

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled): 意味着操作成功完成。--resolve
  • 已拒绝(rejected): 意味着操作失败。--reject

三、Promise基本使用

function foo(url){
    return new Promise((resolve, reject)=>{
        //模拟异步内容
        setTimeout(()=>{
            if(url == 'Jackie'){
                let name = '成功啦,这是数据'
                resolve(name);
            }else{
                let name = '请求失败,参数错误'
                reject(name);
            }
        },3000)
    })
}

const fooPromise = foo('Jackie')

fooPromise.then(res => {
    //then方法传入的回调函数,会在promise执行resolve函数时被回调
    console.log(res);  //成功啦,这是数据
}).catch(error => {
    //catch方法传入的回调函数会在promise执行reject函数时被回调
    console.log(error);  //成功啦,这是数据
})

四、Promise.then方法-接受两个参数

Promise.then方法是Promies对象上的一个方法:它其实是放在Promise的原型上的 Promise.prototype.then 1. then方法传入的“回调函数”可以有返回值

  • then方法本身也有返回值,它的返回值是Promise
  • 如果返回是一个普通值(数值/字符串/普通对象/undefined),那么这个普通值被作为一个新的Promise的resolve值
//示例
fooPromise.then(res=>{
    return 'aaa'
})
//相当于
fooPromise.then(res=>{
    return new Promise(resolve){
        resolve('aaa')
    }
})


fooPromise.then(res=>{
    return 'aaa'
}).then(res=>{
    console.log('111' + res);
    return 'bbb'
}).then(res=>{
    console.log('222' + res);
})

//111aaa
//222bbb
  • 如果返回是一个Promise
fooPromise.then(res => {
    return new Promise((resolve, reject) => {
        console.log(res);
        setTimeout(()=>{
            resolve('11111')
        },3000)
    })
}).then(res => {
    console.log('res', res);
})

//成功啦,这是数据
//res 11111
  • 如果返回的是一个对象,并且该对象实现了thenable

此时then方法中的return也会生成新的promise

fooPromise.then(res => {
    console.log(res);
    return {
        then(resolve, reject){
            resolve('22222')
        }
    }
}).then(res => {
    console.log(res);
})

//成功啦,这是数据
//22222

五、Promise.catch方法

const promise = new Promise((resolve, reject) => {
    reject("这是失败状态")
    // throw new Error("这是失败状态")
})
//第一种方式:then方法传入两个参数,第二个方法则为reject的回调
promise.then(res => {

}, err => {
    console.log(err);
})

//第二种方式:resolve用.then接受,reject用.catch接收
promise.then(res => {

}).catch(err => {
    console.log(err);
})

//第三种方法:在Promise处理失败reject时用throw抛出异常(throw注释关闭则可以测试)

六、Promise.finally方法

无论Promise对象变成resolve或reject状态,最终都会被执行的代码

const promise = new Promise((resolve, reject) => {
    reject("这是失败状态")
})

promise.then(res => {

}).catch(err => {
    console.log(err);
}).finally(() => {
    console.log('finally code');
})

//这是失败状态
//finally code

七、Promise.all方法

Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('11111')
    }, 1000)
})
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('22222')
    }, 2000)
})
const p3 = new Promise((resolve, reject) => {
    setTimeout(()=>{
        resolve('33333')
    }, 3000)
})

//如果传入的东西不是Promise,则会自动转为Promise----Promise.resolve("aaa")
//意见:在拿到所有结果之前,有一个promise变成了reject,那么整个promise都是rejected
Promise.all([p1, p2, p3, "aaa"]).then(res => {
    console.log(res);    //如果promise都为resolve时输出 ['11111', '22222', '33333', 'aaa']
}).catch(err => {
    console.log(err);   //22222
})

八、Promise.allSettled方法

Promise.allSettled方法无论是fulfilled还是rejected时,都会有最终的状态

//p1, p2, p3如上代码
Promise.allSettled([p1, p2, p3]).then(res => {
    console.log(res);  //[{status: 'fulfilled', value: '11111'},{status: 'rejected', reason: '22222'},{status: 'fulfilled', value: '33333'}]
}).catch(err => {
    console.log(err);
})

九、Promise.race方法

Promise.race方法返回一个promise,只要有一个promise最先返回resolve或reject的,就会直接结束且返回

Promise.race([p1, p2, p3]).then(res => {
    console.log(res);   //11111
}).catch(err => {
    console.log(err);
})

十、Promise.any方法

Promise.any方法会等到其中一个promise最先成功resolve则返回;如果promise都是reject,会等到所有promise状态都变成rejected时候报AggregateError: All promises were rejected

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('11111')
    }, 1000)
})
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('22222')
    }, 500)
})
const p3 = new Promise((resolve, reject) => {
    setTimeout(()=>{
        resolve('33333')
    }, 3000)
})

 Promise.any([p1, p2, p3]).then(res => {
    console.log(res);   //11111
}).catch(err => {
    console.log(err);
})