学习Promise总结

211 阅读4分钟

Promise是什么?

Promise是异步编程的一种新的解决方案,比以往通过回调函数和事件来解决异步操作更加强大。
简单来说Promise就是一种异步编程的方式

Promise有什么用?

解决回调地狱

        setTimeout(function () {  //第一层
            console.log('武林要以和为贵');
            setTimeout(function () {  //第二程
                console.log('要讲武德');
                setTimeout(function () {   //第三层
                    console.log('不要搞窝里斗');
                }, 1000)
            }, 2000)
        }, 3000)

输出结果:

武林要以和为贵
要讲武德
不要搞窝里斗

上面的函数第一层是3s,第二层为2s,第三场是1s,但是由于是使用回调函数嵌套回调函数的方式,实现代码顺序执行而出现的一种操作,这种回调函数一层套一层的代码被称为回调地狱,它会造成我们的代码可读性非常差,后期不好维护。

为了解决回调地狱问题,promise横空出世!

promise中使用链式调用的方式解决了回调函数嵌套的情况,让代码看起来更像是同步代码,并且Promise有三种状态,pending(等待态),fulfilled(成功态),reject(失败态),重点:promise的状态是不可逆的,一旦发生改变就不可回溯
看以下代码:

const p = new Promise((resolve,reject)=>{
    resolve(111)
    reject(222)
})

p.then((res)=>{
    console.log('成功的回调',res);
}).catch((err)=>{
    console.log('失败的回调',err);
})

输出结果:

成功的回调 111

我们先将promise的状态置为resolve,后面如果再置为reject则不生效。
再看以下代码:

const p = new Promise((resolve,reject)=>{
    resolve(111)
    reject(222)
})

p.then((res)=>{
    console.log('成功的回调',res);
    return res*10
}).then((res1)=>{
    console.log('成功的回调2',res1);
})
.catch((err)=>{
    console.log('失败的回调',err);
})

猜猜这个代码段的输出结果为什么?
答案为:

成功的回调 111
成功的回调2 1110

从代码中,我们可以看到,在执行第一个then的时候,我们将res的值乘以十以后再return出来,而第一个then返回的值为第二个then中传入的值,这就是promise的链式调用。

Promise中常用的API

promise.all()

概念:在执行多个promise实例时,当所有的promise都执行完毕了才将返回值放入一个数组返回,重点:如果有一个promise的状态为reject(失败)那么其他的promise不再执行,并返回失败的回调。

看代码:

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

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

输出结果:

[ 'p1', 'p2', 'p3' ]

当有一个Promise为失败态时:

const p1 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        console.log('成功的p1');
        resolve('p1')
    },1000)
})
const p2 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        console.log('失败的p2');
        reject('p2')
    },2000)
})
const p3 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        console.log('成功的p3');
        resolve('p3')
    },3000)
})

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

输出结果:

成功的p1
失败的p2
p2
成功的p3

从上面的代码可以看出来,只返回了p2一个reject的返回值,而p1、p3的resolve返回值并没有被返回,但是p1、p3中的输出都被输出了,也就是说,虽然他们的resolve并没有被返回,但是他们这两个promise仍会被执行在这两个promise中的操作仍会生效,只是不会有返回值

Promise.race()

概念:返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝,也就是说race同样是可以传入多个promise组成的数组,但是只返回一个promise,谁跑的快就输出谁
看代码:

var n = 1;
const p1 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        console.log('失败的p1');
        reject('p1')
    },1000)
})
const p2 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        console.log('成功的p2');
        resolve('p2')
    },2000)
})
const p3 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        n++;
        console.log('成功的p3',n);
        resolve('p3')
    },3000)
})

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

输出结果:

失败的p1
p1
成功的p2
成功的p3 2

这里很明显,p1的定时器只有1s所以p1是跑的最快的,所以Promise返回的是reject失败态,并返回p1。
如果定时器时间一样呢?

var n = 1;
const p3 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        n++;
        console.log('成功的p3',n);
        resolve('p3')
    },1000)
})

const p1 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        console.log('失败的p1');
        reject('p1')
    },1000)
})
const p2 = new Promise((resolve,reject)=>{
    setTimeout(()=>{
        console.log('成功的p2');
        resolve('p2')
    },1000)
})

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

输出结果:

成功的p3 2
p3      
失败的p1
成功的p2

定义在最前面的p3先输出,返回一个成功的promise