00:00
大家好,我是学习园地的特约讲师高洛峰,上节课咱们讲的post曼和前边的接口都是为阿帽呢做准备,那这节课呢,咱们来学习一个新的知识点,在学习2MA之前呢,我们来学习一下ES6中跟我们新添加的promise,那promise呢主要用于异步的处理,可以将异步的操作队列按照期望的顺序执行,返回符合预期的结果,这是它的一个定义。那么咱说了学X,为什么要先学promise?因为在阿里边这种异步请求大量的应用到了promise。无,呃,咱们无非说是它是用到了大量的promise,不如说阿MOS呢是基于promise的,所以呢,咱学习S这种异步处理之前,最好先学一下promise,那promise是干嘛的?就是解决异步回调的问题。那有的说什么是一步回调啊,咱们先给大家举个例子来说,那我直接上代码。让大家了解一下,那呃,那咱们就在服务器上建吧,因为咱们学阿奇莫斯的时候呢,咱们为了不跨域,咱们就在这里边新建一个。
01:06
X。新建一共订单在这里边我们新建一个。一个二件。在这里边。呃,Pro点人TL错啊。那我直接咱先不创建项目啊,我直接用web打开。直接打开,然后这里边直接写一个。应用单位方向啊。直接写呃标签,那我们在这块先看一下。我们以前做,呃,咱们在做项目的时候,经常需要异步请求服务器,多次请求,而且多次请求之间呢,还是有关系的,也就是第一次请求返回的数据里边有URL,我们通过第一次请求返回的URL再去请求服务器,这样的话层层的调用就会形成回调地域来,我们先模拟一下啊,回。
02:08
模拟下。为调。一。是一个什么情况,比如说假设我们用的是井二位,里边我们用带的方法请求服务器,比如说URL,咱假设啊,你可以是自己去想象那个URL,然后呢,我们这块接收一个数据A1,然后里边。咱们用箭头函数啊,在这里边处理,这里边儿是一系列。的处理,当然意思是有很多条代码,然后呢,处理完之后呢,再返回的DATA1里边,从服务器请求那个数据里边,那我们还需要什么,还需里边还有URL,那我们还得从贝塔一里边,假如说有个URL2,我们从这里边。再请求一下这个UR2获取到贝塔二。获取的DATA2,然后在DATA2里边呢,我们这块又去过处理一系列的动作之类的,然后呢,在DATA2里边返回DATA2里边还有URL,那我们DATE2里边的URL,我们又获取三。
03:07
这样的一个情况,那在这里边又处理一系列动作,然后呢,在DATE3里边,我们有可能还有一个URL,那我们再去获取什么DATE4。这样的一个情况,然后在这里边再处理一系列动作等等等等,那形成了这样层层的一个回调的一个嵌套的关系,那这种呢,就称为回调地域,为什么称为回调地域呢?一是层次结构,当然咱们这块只是模拟一个结构,你看着层次结构没关系,对不对?当然这里边儿如果真的有一系列代码,代码有几百行的话,那你就真的不知道这个对应的是哪一层回调。那代码的可读性差,有可能还会出现一系列错误,逻辑上的不好处理等等一系列问题,那想解决这个问题,所以在ES6里边儿给我们就增加了一个功能,叫做promise,增加了一个这个功能。那比如说那我第一步处理,因为咱现在呃,来回连接服务器比较麻烦,所以呢。
04:00
我们先用set time,呃,Set timeout来模拟一下上面那个情况,一个异步处理,比如说一层set time out也相当于异步,对不对,因为它是一秒钟,或者是你指定的几秒钟的时间执行的一个什么,执行的一个回调函数,执行回调函数,比如说在这里边我们嗯,打印一下。这是第一层。点ROOG我们打一下,然后在这里边我们by time out里边我们再来一次,然后比如说也是一秒钟吧,那我们再。来一下。模拟的一步,你就想那是请求URL,然后执行和我们一秒钟之后再执行,都同样是异步处理的,那我们这里边改成这是第二层。然后同样在这里边,我们再来一层。太然后。这个间隔函数应该应不应该陌生啊,因为咱们是讲过的,所以呢,我就不多说什么是进头函数了,它是什么原理了啊。然后这里边我们再来一下,这是第三层。
05:00
那我用三层来模拟,那有可能有十层八层的,对不对,来我们运行一下,当然了,它是在控制台里边用colo打印的,所以呢,我们需要把这个控制台调出来。我们刷新一下,再重新来一下,你看一秒一个一秒一个第二层第三层对不对,这就是我们平时写代码的时候,如果你代码很复杂的时候,就是一种回调地域的一个情况,那promise怎么解决它呢?那我们就看一下,那promise呢,我们它是通过实例生成,那通过实例生成之后呢,我们可以用一就然后那个单词,然后呢,分别指定它的两个状态,一个是解决问题的状态,一个是拒绝解决问题的,两个状态分别是两个回调方法,你看一下,我试一下用一个new,一个promise prom这个它里边需要传一个回调方法,你看传一个回调方法,回调方法里边再接收两个参数。看这里边还是我们回调方法,再接收两个回调方法,所以呢,在这里边再接收两个,一个是一个是叫做receive。
06:02
和一个。这一习题你在这里边是个回调函数,看好了是个回调函数,那这两个回调函数你直接调用就行,不用声明,那在这里边比如说。我们这里边开始执行了。这是第一层对吧,然后呢,在这里边我们想往下执行对吧,往下执行。我们怎么办呢?我们就得需要你看。他如果我们处理完这里边,假如说有一系列动作,如果让他往下执行的话,我们这块标一个TH1就不用嵌套了,通过这个方法就行,然后呢,他接收到一个数据。也是一个回调方法,作为一个参数,那我们怎么能将这个参数的数据传到这里边来呢?在这里执行完不用嵌套,跟嵌套差不多,但是呢,是这种并行的结构了,不是这种串行的结构了,那怎么办呢?我们这里边调用receive。这个方法,这个方法名是不是re l VE小E加不加这就行了,因为这只是一个方法名嘛,对不对,那我们调用将我们的数据传到这里边来,你比如说这是第二层。
07:10
那我们在这里边用1PROMISE,你不用在这里边继续再写一层嵌套往里边去去做,当然我现在还没用到一步处理啊,不用嵌套往里做,那你怎么办呢?你可以直接调用这个方法,他同意对吧,就解决问题,怎么解决呢?把数据传给这个回调参数,在这里边去解决。你看,Re LG。我们运行一下。你看一下这是第一层第二层,当然了,没用时间的关系,直接就过来对不对,那这里边第二个参数拒绝什么意思呢?如果我们同意是在这里执行,那如果我调用这个拒绝,Re。这1CT拒绝,假如这里边是一个错误,对不对,这是一个呃,错误。那我们根据判断,比如说如果我们返回的值呃是成功了,那我们就调用这个,如果我们返回值是错误的,那我们调用这个,调用这个它也到这里就行吗?不是在th hen这个方法里边,然后这个方法里边有两个参数,第二个参数就是。
08:05
专门处理我们错误的就是拒绝的时候会回到到这里边第二个参数,那第二个参数呢,也是一个回调方法,那我们E作为参数,用镜头函数指定在这里边就N。然后rog吧,我们打印一下这个E,这个错误,你看现在。我们就可以做判断,你看如果是第一层,然后这是一个错误,就到哪去了,就到这来了,对吧,反应这是一个错误,如果我把这个。打开关闭,把这个打开当然用判断啊,用咱们数据里边返回的数据是成功还是失败的,根据里边的数据我们去判断,成功了我们到哪里去做,失败去哪里去做,那比我们在回调里边用艺术语句判断要好一些,对吧,代码更清楚一些,你看。这就变成什么第一层第二层没有错误了,那两个如果都开呢,那两个没有都开的,因为它是一个排斥的关系,对不对。对吧,你看两个都开,它第一个调了第一个就不会调用第二个,那同样你把它这个放到上面。
09:01
你看调一个他就不会掉,第二个你看啊。这是一个错误,看到了吧,他俩是排斥的关系,只会有一个生效,我们会有两个生效就可以了,那同样如果在一层,在这里边,假如说在这里边我们打印完之后,我还想往下执行呢,有这么几种办法,一种呢是return,返回promise,再写一个。这里边再来一个。Re so和。这里边是个参是呃是函数啊,Re so和re这1CT,然后我们在执行在这里边,那只需要在这里边,我们再调一下这个里边的。这个里边的。这个写错了。哦,再调用这个方法,或者是调用这个里边的什么这个方法,这上面是一个道理啊,你看。这里面写上这是第三层,那同样在这块我们再加一个什么enn,然后我们在这里边再写res接收这里边返回来的,然后res.RO log打印。
10:09
来,我们看结果你看。啊,没有定义一个promise,是不是我们写错了,看一下啊。呃,Pro这块promise必须得用这上面一样,里边new返回这个用promise啊来我们看下这块,你看这是第三层,那同样如果有第四层,你第十层都可以,你每一层都去这么写就可以了,每一层都去这么写另一个,但说这有没有简便方法呀,这么写有简便方法,怎么个简便方法呢?我们不是去用这种,你看啊把它注掉。你看我们第二种方法是干嘛呢?这块使用返回直接不就不用用对象了,把它看成是一个静态资源来用,那这里边有一个什么。拒绝和解决问题的,对吧,Resolve和reject这两个方法,这里边儿我们加上这是第三层,你看是一样的,这俩效果是一样的啊。
11:00
这俩效果是一模一样的,然后我们来刷新一下。你看这是第三层也可以了,那有没有更简单的方法呢?也有更简单方法,我们再来往下再继续,怎么继续呢?我们直接返回,在这里边返回一个字符串,它就会自动相当于给我们加上promise,如果自己返回值的话,我们加默认是resource,对吧?如果是什么拒绝的话,你promise你得那么去写啊,但是如果就是同意往下执行,把数据传过来,但是数据你可以是一个字符串。咱们现在都是用券第三层啊,比如说S消息。这是第三层。你是什么都行啊,什么格式都行。这是第三层,然后呢,这里边调用的就是结果,把它传过来也是一个对象mess对不对,你看都行。来,我们再增下,还是一样的效果。所以呢,你可以通过这三种中的任意一种去往下传递。这样的话,就把这种嵌套的关系,层层嵌套的义务处理变成了这种竖式的,然后然后看起来比较清晰,对不对,那再有。
12:05
那假如说用异步处理,你这还没用上异步处理,他说没用一步处理的话,你这种按步骤执行的,因为你看讲这理解了对吧,可以将异步操作的还队列按期望的顺序返回预期的效果对不对。可以在对象之间传递操作pro对不对,那异步处理不是异步处理都可以去通过这种风格,你看这种风格容易理解,便于维护对吧。多个异步符合合并的必须解决等等都是它的一个优势,所以有这种层层调入的,你就用这种,那假如像文拟异步的,你看假如这种方式异步处理怎么办呢?你看这是第一层,那我这会,嗯,这是第二层,我不在这里边去使用,那我在time out这里边加上一个回调方法,我这里边再加上一个一秒钟,然后调用这个。你看让这些。因为只有调用。它的时候才能够执行它的方法对不对,但是如果我在这块,你看用这种方法,假如用直接返回的方法,这样在这块调用,它能调用的到吗。
13:10
在这块。如果直接用返回的方法,他能调得到吗?把这个拿过来。放在这儿。这里边儿。用直接返回的这个方法。你看能听到吗。我想是调用不到的,因为你看一下他会发现这块是没有定义。不会出错,但是没有定义,你看啊,这个出错了,没有这个定义,这个方法还是这个没有定,为什么是出现没有定义,因为我们在执行这个的时候,对吧,他在异步处理,在处理这个时候没等处理完呢,这等等一秒钟之后才处理这个对不对,但是呢,我们这个方法已经开始执行了,那已经执行了,对吧,这个数据是没有传过来的数据。对吧。所以是不行的,那我们如果用到这种方式,我们怎么做呢?我们最好是用这种方式来做。
14:01
当然了,里边也有什么A,还有呃,An的那种异步请求的处理方式啊,你可以用这种方式处理,然后把这个我们写到哪去呢?写到这个里边。写到这个里面,你看一下,这样的话我们就得等它这个返回值,等着里边运行完之后,返回这个对象的时候才能往下执行,写在这个对象里面,这样的话我们才能一步的去处理来我们刷新一下。第一层第二层。这里边儿这么直接返回不行,在这里边必须得要用什么,要用这个re solve啊。先说这个。我们在。刷新一下。第一层第二层第三层你看就解决了这种问题,对吧,不然的话,它有一个什么同步异步的这样的一个问题啊,解决不了。那我们再简化一下,其实我们像这样处理就是这样反复处理的话,你都是用promise,它可以调用这种方式,对不对,那我们通常每一层处理的时候呢,你这么写还是不清晰,但是他要的是这种结构,我们可以怎么办呢?我们可以单独做一个方法,比如说嗯,Action DEMO。
15:10
我们做一个这样的一个一个方法来处理多少层都可以,比如说这里边来一个消息,咱们现在就模拟啊和一个题时间吧,这两个,那我这块。里边我们直接用什么,我们直接用这个。你看直接把这个方法放在这儿。DEMO,然后直接返回的是这个这里边的这个消息,那我们就是什么ES。嗯。我这吧。直接ess返回,把这个消息给他,那时间呢,那我们就是用T乘1000。我们可以写个方法,就是1000是一秒嘛,T5传几就是几秒嘛,对吧,是这样的一个方法,然后返回这个。这样的一个结构,你看我们单独用promise,这样的话,只要有个promise它就会执行,然后那我们把这个方法换一下,你看这里边儿我们就不这么用了。
16:07
感觉复杂对不对?那我们想让它变成简单的用法,怎么用呢?这里边儿。看一下啊。看一下它的结果是不是咱们断了,然后然后里边大括号。里边大括号。这里多了一层。是这样的。才可以。那上面少不少啊。没问题,然后我们在这里边直接调用DEMO,对吧,传一个消息,这是第三层,然后呢,几秒呢,比如说我们应的是两秒之后执行这样的一个情况,那我们在这块是不是直接I就行了,因为它直接消息我们传过来不是对象啊,对吧?来我们运行一下。嗯。刚才代码结构有问题啊,我把这个错误这块先去掉。
17:03
这块是,然后执行这个大块就没问题。用不?这没问题,上边我看是不是哪块代码问题。这上边怎么就变黄了,那肯定上面是缺东西,我们看一下这块啊,这是对应这个括号的,那我们外层应该还少一层括号,你看。就可了,因为这个是这个里边的。括号这里面括号。他还得加一个这个根号,因为它是构造方法对不对,这才对,来我们运行一下。张新一下,这是第一层第二层,诶第三层没有定义,我们看一下啊。标语receive t。这是第三层。DEMO要。So。为定义,因为我们这里边得返回的是promise对象,这里边直接调用不行,对吧,返回的promise对象才能用promise对象里边的receive调用到它,所以这块我们得加一个return,你看我们上面这里边有没有啊,这块也有这样才可以啊来必须得返回啊。
18:13
我们来运行一下第一层,第二层。两秒钟之后第三层,你看这样才可以啊。才能解决这个问题,这就是我们呃promise的最基本的用法,两个参数,一个同一个句标,那如果有问题或者有异常的,我们还可以有一个catch,比如说在最后有很多层统一处理错误,Catch ch pat,这里边呢是一样的,需要一个呃回调函数。比如说E2。当这里边儿有问题,任何一个步骤有问题,那我们都可以让他统一跳到这里边去,不用在每个,然后里边去处理,对吧,把错误放在一起去处理。不然的话,我们每一个错误都得写一遍,因为后边这块都得写一遍,对不对,那你看我这里边儿,假如说。要用e.OOG,假如说我们在第一层这块。
19:00
这块我们来这开开吧,这是一个错误,你看它会调用哪啊,调用catch,你看这是一个错误,直接到catch里边来,其实跟开差不多,那我们不用调用这个,你比如说我们抛出异常行不行啊THRW肉扔出一个日常异常。嗯,这是一个E一个错误,你看我们直接手动的扔出一个,抛出一个异常,会不会执行呢?你看也会执行对吧,所以呢,两种方式,一种调用这个,一种用异常的方式去解决就可以了。所以这是promise的一些基本的用法,这样解决的就是我们上面这种回调地位的方法,那除了这种方式,那有的时候呢,我们在使用的时候,还有一种叫做并发请求,什么叫并发请求呢?你比如说我们一个页面的一个项目的首页,那有可能它不是这种关联的关系请求不是说第一次请求拿到结果通过里边UR的请求,第二个两个是并行的,比如说去既取首页中的栏目数据,又取首页下边的,比如说友情链接的数据,这俩是并行处理的,对不对?
20:03
那咱俩并行处理的时候,那个结果我们怎么怎么去做呢,把结果放到一起去应用。不然的话,我们得单个去获取,单个去处理,然后我们再合并,对吧,所以呢,在里边给我们提供一个。比较方便的一个方法叫什么pro叫做A这个方法。看好了,这是,呃,提供了一个这个。这个方法中呢,要我们传的是一个数组,那意味着告诉什么?每一个既然是传数组,就意味着要我们可以传多个promise。传多个promise,那我们这里边用一个pro promise一个对吧,然后呢,既然是数组,那我们还可以用第二个pro promise,那我们还可以用第三个第四个,那咱们用两个来模拟一下就行了,然后这个promise里边,咱说每个promise里边咱们需要两个参数对不对?一个是什么?呃,Re。一个。
21:03
一个同意一个拒绝,这个方法打开,然后同样在这个里边。我们也需要。这样去处理,然后在这里边,这样的话就可以并发请求了,两个写在一起,它俩没有关联关系,咱俩是一起同相当于什么一起的一个关系,不是说有先后的一个关系,对吧?那这里边儿我们在处理数据的时候,比如这里边做一个网络请求,请求分类信息,这里边请求什么友情链接信息,假如是这样,那咱们模拟异步请求,比如说set out这里边。我们用上。这个方法,比如说在这块一秒钟。嗯,我们请求把结果用这个传过去,对吧?So,传传过去这是第一个。请求。这是第一个请求。这块啊,诶拿过来,然后同样这里边。放在这里边来,这是第二个请求。那两个是并行请求的,对吧,那我们需要干嘛呀,请求的结果会直接统一到一个在里边。
22:09
到一个这里边来,当然后边也可以再看什么的,对不对,但是这里边儿这个处理这个结果,它就不是什么,它就不是。一个一个了,而是一个数组,这个数组呢,就包含这两个传过来的数据,当然我们传字符串也行,传对象也行,对不对,它会把这两个合并的这里边,所以这个is这里边的零代表的有可能是这个的里边给我们的返回的值,对吧,要下一步请求的值,那一呢,代表的是这个返回值,那我们直接打印一下,你看它是不是柱子第2ROG。我们打一下。刷新一下。你看变成了一个数组,把两个合并到一起去了,这是第一个请求,这是第二个请求,所以呢,我们有并发请求的时候,用promise,用all方法非常有用,一起请求,然后统一把结果都传到这里边,想象一下,如果你不用promise这个all方法,你想做并发请求,你该怎么做,对吧?
23:02
当然这只是到这里边只是普的一些基本用法,但这些呢就足够我们用了,那咱们学了这个,咱们在学XO的时候,那我在使用这个这方法是干嘛的,对吧,你就不会陌生了,因为阿是基于。好,谢谢大家。
我来说两句