还不会用Promise吗?那就赶紧来看看吧!

445 阅读3分钟

前言

请大家和我想象一个场景,你去某快餐店点餐,点完餐后,你会进入等待状态,过了一会之后,你会得到结果。要么你的快餐制作成功,你可以享用你的食物,要么 因为其他某些原因(可能是原材料不足等)导致你的快餐制作失败了,你的食物自然就吃不到了。
这是在生活中很常见的情景,但是和Promise有什么关系呢?

什么是Promise? 为我们解决什么问题?

Promise 是es6提供的一个对象,Promise中文是保证、承诺的意思,代表了未来将要发生的事件,用户来传递异步操作的消息。在这之前 由于函数在js中是一等公民,可以用来传参,就导致了大量回调函数的情况,从而不可避免地陷入到回调地狱中去,而Promise这时候就闪亮登场了

Promise的使用

话不多说,先打印个 Promise 看看

3.png 通过 console.dir(Promise) 我们看到 Promise是个构造函数。它自身有 all race resolve reject 几个方法,在原型上面有 then catch 方法。那我们就来new一个Promise

5.png
Promise接收一个函数,传入两个参数 resolve 和 reject,分别代表异步操作成功后的回调和异步操作失败后的回调。then方法捕捉到变化,执行回调,resolve和reject抛出结果作为then方法函数中的参数。 在这里联系我们的快餐例子,你可以理解为 resolve是告诉你出餐成功,reject则是出餐失败,then则代表得到出餐结果后的操作(得到食物或者出餐失败的原因)

7.png


由此我们得知Promise有三种状态,分别是pedding(进行中),fulfilled(成功),rejected(失败)。 而状态的改变 也只能是:
pedding(进行中) --> fulfilled(成功) ;
pedding(进行中) --> rejected(失败);
而且Promise 一旦发生状态的改变,就无法再更改。

11.png

then的链式调用

那如何解决回调地狱的问题呢?可以在then方法后面再调用一个then方法。因为Promise.prototype.then()返回的是一个新的 Promise, 所以我们可以链式调用。在Promise的原型上我们之前还看到过一个catch(),一旦then()中抛出错误,就会调用catch()的回调函数。建议不要在then()中定义失败的回调函数(上图中then()的第二个参数),而是使用catch()

10.png


我们对之前的代码进行了调整,我们不在then()里面获取失败的回调了,而是在末尾加了一个catch().因为 Promise 对象的错误具有"冒泡"性质,会一直向后传递,直到被捕获为止。

10.png

resolve(),reject()

Promise.resolve() 默认就是成功状态 而不是pedding

11.png
Promise.reject() 默认就是失败的Promise

13.png
同时Promise.reject() 可以用来抛出异常

14.png

all()

Promise.all() --> 批量处理Promise。接收一个数组,并且在所有异步操作执行完后才执行回调
成功回调 --> 返回一个结果数组
失败回调 --> 抛出错误

15.png

race()

Promise.all() 批量处理Promise。接收一个数组。只取一个,不管状态成功与否,哪个返回快就用哪个。

16.png

队列

我们之前讲过的很多接口都是类似批量处理数据或者哪个快用哪个,而现在我们要按顺序来执行Promise任务 也就是 下一个Promise要等上一个Promise任务完成之后再来执行。

18.png
每一次返回新的Promise,后面的then是根据新Promise所做的处理,会等待新Promise完成之后再执行。以此类推 实现Promise顺序执行的队列效果

结语

总的来说Promise还是挺重要的,起码得会用。其实我总结的还差很远 比如Promise.allSettled(可以理解为Promise.all的扩展)没有说,微任务宏任务也没说。加上之前上学语文就学的不太好,,,措辞好像也有点乱。所以求大家轻喷,这也是我的第一篇文章,还是厚着脸皮希望大家能给我一些支持!!!谢谢大家了。