Promise网络请求,异步编程封装,优雅

2020-10-13  本文已影响0人  似朝朝我心

1.什么是Promise,Promise到底是做什么的,有什么作用?

Promise(承诺)是ES6中一个非常重要和好用的特性,Promise是针对异步编程的一种实现解决方案,Promise内部可以用来处理异步事件和操作,即可以用于包裹(wrapper into)封装异步操作代码。

2.常见的应用场景。

比如我们想封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的同步编程一样将结果直接返回。


如果按照这样排着队来执行代码,同步编程就会带来一个严重的问题,那就是网络阻塞。

比如说,我们的用户在电商购物平台浏览进行某种操作(这些生鲜水果真不错,我想买几斤,用户在点击某个喜欢的商品,一般都会进一步了解商品的详情,这时候就会想点击了解下关于商品的详情,看看评论,才决定下不下订单)的时候,也就是说,用户的所有这些不确定性点击事件,会突然间要向我们的服务器发送一个网络请求(这时候的JS代码就会去请求有关这个商品的详情页反馈给用户),而网络请求一般情况下呢都是比较耗时的。

如果这个时候,我们的网络请求是同步(按照顺序排着队执行代码,不许插队)的话,就意味着用户面临网络阻塞的情形(哎哎!兄弟,我在咨询相关的业务办理呢,还没到你呢,到后面排队去,排队去!),这就导致用户界面上什么东西都不会显示,这时候就会出现了网页空白,因为当前的js代码执行已经被阻塞了,它要等到当前网络请求任务完成后,才轮到它。),

所以这时候呢,我们会传入另外一个函数,在数据请求成功时,在数据请求成功时,将数据通过传入的函数回调回去。

就是当我们有一个网络请求的时候,我们会直接开启一个异步的任务线程,让这个异步任务专门单独处理我们的请求(相当于我们去银行开办业务的时候,银行业务众多且杂,如果所有业务都集中在一个窗口办理的话,那就非常不现实了,因为有的人想转账,有的人想存钱投资理财(办理几几十分钟),有的人想单纯地办卡,七八分钟就可以办好的业务,那也要让他们安安静静的排队等待一整天?等到大晚上吗?

如果这时候,采取分门别类的对策,开出一个个专门属于让我们办理具体业务的窗口的话,那让用户办理起业务就方便了,反过来想,这就好比我们的异步编程有专属于我们自己的通道,办卡在1号窗口,转账在2号窗口,这样我们就避免了集中在一个窗口里面排着长长的等侯队列,而直接去1号窗口办理业务即可。)

但开辟出的1号窗口,如果人太多的话,依然是排队等候呀,没错,这就是所谓的回调地狱了。

3.Promise请求过多也会带来问题。

当我们的网络请求非常复杂时,会出现回调地狱的情形,(也就是一个回调函数里面还需要一个回调,回调函数里面又需要一个回调,呈现出多层级嵌套的回调关系。)

4.网络请求的回调地狱

我们可以考虑一下下面这种嵌套场景。

总结:上面的代码是可以正常运行并且能够获取到我们想要的结果,不过,这样的代码难看且不说,(当代码块足够多的时候)维护起来也是要死的,因此我们需要一种更加优雅的方式来进行这种异步操作,也就是ES6为我们提供的Promise类,可以非常优雅地进行异步操作

5.Promise的基本语法使用

使用定时器(setTimeout)来模拟异步操作

6.OK,通过上面的例子,我们已经清晰认识到Promise的基本使用封装写法,那什么情况会用到Promise呢?

7.Promise的三种状态

当我们在开发中有异步操作时,就可以给异步操作包装一个Promise网络请求,通过异步操作之后会出现三种状态

图解:

8.Promise的异步处理形式。

一种是.then()和.catch()结合形式


另一种直接在.then()回调函数里面操作,即.then(函数1, 函数2)

9.Promise的链式调用标准。

其中一种我们已经在上面的例子实现了(用链式编程解决回调地狱的情形),下面我们看下Promise另一种的链式调用标准。

需求:

代码原型:



我们上面考虑到的都是网络请求成功后拿到数据的情形,那有没有可能在某一层的网路请求被拒绝pass掉了,导致后面层拿不到数据呢?这时候我们该怎么办呢?


除了reject()和.catch()搭配使用处理异常外,throw 也可以直接抛出异常。

10.Promise.all()方法的使用,在某次开发需求中,可能会遇到需要发送2次网络请求的情形,这时候就会用到Promise.all()方法。

先来看下Ajax是如何操作的。



ES6中Promise.all()方法如何操作的。



上一篇下一篇

猜你喜欢

热点阅读