race是什么意思

更新时间:2022-11-24 16:45:14 阅读: 评论:0


2022年11月24日发(作者:新东方一对一外语课事件)

ES6---newPromi()使⽤⽅法

2015年6⽉份,ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promi被列为正式规范。作为ES6中最重要的特性之⼀,我

们有必要掌握并理解透彻。本⽂将由浅到深,讲解Promi的基本概念与使⽤⽅法。

ES6Promi先拉出来遛遛

复杂的概念先不讲,我们先简单粗暴地把Promi⽤⼀下,有个直观感受。那么第⼀个问题来了,Promi是什么玩意呢?是⼀个类?对

象?数组?函数?

别猜了,直接打印出来看看吧,(Promi),就这么简单粗暴。

这么⼀看就明⽩了,Promi是⼀个构造函数,⾃⼰⾝上有all、reject、resolve这⼏个眼熟的⽅法,原型上有then、catch等同样很眼熟

的⽅法。这么说⽤Prominew出来的对象肯定就有then、catch⽅法喽,没错。

那就new⼀个玩玩吧。

varp=newPromi(function(resolve,reject){

//做⼀些异步操作

tTimeout(function(){

('执⾏完成');

resolve('随便什么数据');

},2000);

});

Promi的构造函数接收⼀个参数,是函数,并且传⼊两个参数:resolve,reject,分别表⽰异步操作执⾏成功后的回调函数和异步操作

执⾏失败后的回调函数。其实这⾥⽤“成功”和“失败”来描述并不准确,按照标准来讲,resolve是将Promi的状态置为

fullfiled,reject是将Promi的状态置为rejected。不过在我们开始阶段可以先这么理解,后⾯再细究概念。

在上⾯的代码中,我们执⾏了⼀个异步操作,也就是tTimeout,2秒后,输出“执⾏完成”,并且调⽤resolve⽅法。

运⾏代码,会在2秒后输出“执⾏完成”。注意!我只是new了⼀个对象,并没有调⽤它,我们传进去的函数就已经执⾏了,这是需要注意

的⼀个细节。所以我们⽤Promi的时候⼀般是包在⼀个函数中,在需要的时候去运⾏这个函数,如:

functionrunAsync(){

varp=newPromi(function(resolve,reject){

//做⼀些异步操作

tTimeout(function(){

('执⾏完成');

resolve('随便什么数据');

},2000);

});

returnp;

}

runAsync()

这时候你应该有两个疑问:1.包装这么⼀个函数有⽑线⽤?e('随便什么数据');这是⼲⽑的?

我们继续来讲。在我们包装好的函数最后,会return出Promi对象,也就是说,执⾏这个函数我们得到了⼀个Promi对象。还记得

Promi对象上有then、catch⽅法吧?这就是强⼤之处了,看下⾯的代码:

runAsync().then(function(data){

(data);

//后⾯可以⽤传过来的数据做些其他操作

//......

});

在runAsync()的返回上直接调⽤then⽅法,then接收⼀个参数,是函数,并且会拿到我们在runAsync中调⽤resolve时传的的参数。运⾏

这段代码,会在2秒后输出“执⾏完成”,紧接着输出“随便什么数据”。

这时候你应该有所领悟了,原来then⾥⾯的函数就跟我们平时的回调函数⼀个意思,能够在runAsync这个异步任务执⾏完成之后被执⾏。

这就是Promi的作⽤了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执⾏完后,⽤链式调⽤的⽅式执⾏回调函数。

你可能会不屑⼀顾,那么⽜逼轰轰的Promi就这点能耐?我把回调函数封装⼀下,给runAsync传进去不也⼀样吗,就像这样:

functionrunAsync(callback){

tTimeout(function(){

('执⾏完成');

callback('随便什么数据');

},2000);

}

runAsync(function(data){

(data);

});

效果也是⼀样的,还费劲⽤Promi⼲嘛。那么问题来了,有多层回调该怎么办?如果callback也是⼀个异步操作,⽽且执⾏完后也需要有

相应的回调函数,该怎么办呢?总不能再定义⼀个callback2,然后给callback传进去吧。⽽Promi的优势在于,可以在then⽅法中继续

写Promi对象并返回,然后继续调⽤then来进⾏回调操作。

链式操作的⽤法

所以,从表⾯上看,Promi只是能够简化层层回调的写法,⽽实质上,Promi的精髓是“状态”,⽤维护状态、传递状态的⽅式来使得

回调函数能够及时调⽤,它⽐传递callback函数要简单、灵活的多。所以使⽤Promi的正确场景是这样的:

runAsync1()

.then(function(data){

(data);

returnrunAsync2();

})

.then(function(data){

(data);

returnrunAsync3();

})

.then(function(data){

(data);

});

这样能够按顺序,每隔两秒输出每个异步回调中的内容,在runAsync2中传给resolve的数据,能在接下来的then⽅法中拿到。运⾏结果如

下:

猜猜runAsync1、runAsync2、runAsync3这三个函数都是如何定义的?没错,就是下⾯这样(代码较长请⾃⾏展开):

functionrunAsync1(){

varp=newPromi(function(resolve,reject){

//做⼀些异步操作

tTimeout(function(){

('异步任务1执⾏完成');

resolve('随便什么数据1');

},1000);

});

returnp;

}

functionrunAsync2(){

varp=newPromi(function(resolve,reject){

//做⼀些异步操作

tTimeout(function(){

('异步任务2执⾏完成');

resolve('随便什么数据2');

},2000);

});

returnp;

}

functionrunAsync3(){

varp=newPromi(function(resolve,reject){

//做⼀些异步操作

tTimeout(function(){

('异步任务3执⾏完成');

resolve('随便什么数据3');

},2000);

});

returnp;

}

在then⽅法中,你也可以直接return数据⽽不是Promi对象,在后⾯的then中就可以接收到数据了,⽐如我们把上⾯的代码修改成这

样:

runAsync1()

.then(function(data){

(data);

returnrunAsync2();

})

.then(function(data){

(data);

return'直接返回数据';//这⾥直接返回数据

})

.then(function(data){

(data);

});

那么输出就变成了这样:

reject的⽤法

到这⾥,你应该对“Promi是什么玩意”有了最基本的了解。那么我们接着来看看ES6的Promi还有哪些功能。我们光⽤了resolve,

还没⽤reject呢,它是做什么的呢?事实上,我们前⾯的例⼦都是只有“执⾏成功”的回调,还没有“失败”的情况,reject的作⽤就是把

Promi的状态置为rejected,这样我们在then中就能捕捉到,然后执⾏“失败”情况的回调。看下⾯的代码。

functiongetNumber(){

varp=newPromi(function(resolve,reject){

//做⼀些异步操作

tTimeout(function(){

varnum=(()*10);//⽣成1-10的随机数

if(num<=5){

resolve(num);

}

el{

reject('数字太⼤了');

}

},2000);

});

returnp;

}

getNumber()

.then(

function(data){

('resolved');

(data);

},

function(reason,data){

('rejected');

(reason);

}

);

getNumber函数⽤来异步获取⼀个数字,2秒后执⾏完成,如果数字⼩于等于5,我们认为是“成功”了,调⽤resolve修改Promi的状

态。否则我们认为是“失败”了,调⽤reject并传递⼀个参数,作为失败的原因。

运⾏getNumber并且在then中传了两个参数,then⽅法可以接受两个参数,第⼀个对应resolve的回调,第⼆个对应reject的回调。所以我

们能够分别拿到他们传过来的数据。多次运⾏这段代码,你会随机得到下⾯两种结果:

或者

catch的⽤法

我们知道Promi对象除了then⽅法,还有⼀个catch⽅法,它是做什么⽤的呢?其实它和then的第⼆个参数⼀样,⽤来指定reject的回

调,⽤法是这样:

getNumber()

.then(function(data){

('resolved');

(data);

})

.catch(function(reason){

('rejected');

(reason);

});

效果和写在then的第⼆个参数⾥⾯⼀样。不过它还有另外⼀个作⽤:在执⾏resolve的回调(也就是上⾯then中的第⼀个参数)时,如果抛

出异常了(代码出错了),那么并不会报错卡死js,⽽是会进到这个catch⽅法中。请看下⾯的代码:

getNumber()

.then(function(data){

('resolved');

(data);

(somedata);//此处的somedata未定义

})

.catch(function(reason){

('rejected');

(reason);

});

在resolve的回调中,我们(somedata);⽽somedata这个变量是没有被定义的。如果我们不⽤Promi,代码运⾏到这⾥就直

接在控制台报错了,不往下运⾏了。但是在这⾥,会得到这样的结果:

也就是说进到catch⽅法⾥⾯去了,⽽且把错误原因传到了reason参数中。即便是有错误的代码也不会报错了,这与我们的try/catch语句

有相同的功能。

all的⽤法

Promi的all⽅法提供了并⾏执⾏异步操作的能⼒,并且在所有异步操作执⾏完后才执⾏回调。我们仍旧使⽤上⾯定义好的runAsync1、

runAsync2、runAsync3这三个函数,看下⾯的例⼦:

Promi

.all([runAsync1(),runAsync2(),runAsync3()])

.then(function(results){

(results);

});

⽤来执⾏,all接收⼀个数组参数,⾥⾯的值最终都算返回Promi对象。这样,三个异步操作的并⾏执⾏的,等到它们都执⾏

完后才会进到then⾥⾯。那么,三个异步操作返回的数据哪⾥去了呢?都在then⾥⾯呢,all会把所有异步操作的结果放进⼀个数组中传给

then,就是上⾯的results。所以上⾯代码的输出结果就是:

有了all,你就可以并⾏执⾏多个异步操作,并且在⼀个回调中处理所有的返回数据,是不是很酷?有⼀个场景是很适合⽤这个的,⼀些游戏

类的素材⽐较多的应⽤,打开⽹页时,预先加载需要⽤到的各种资源如图⽚、flash以及各种静态⽂件。所有的都加载完后,我们再进⾏页

⾯的初始化。

race的⽤法

all⽅法的效果实际上是「谁跑的慢,以谁为准执⾏回调」,那么相对的就有另⼀个⽅法「谁跑的快,以谁为准执⾏回调」,这就是race⽅

法,这个词本来就是赛跑的意思。race的⽤法与all⼀样,我们把上⾯runAsync1的延时改为1秒来看⼀下:

Promi

.race([runAsync1(),runAsync2(),runAsync3()])

.then(function(results){

(results);

});

这三个异步操作同样是并⾏执⾏的。结果你应该可以猜到,1秒后runAsync1已经执⾏完了,此时then⾥⾯的就执⾏了。结果是这样的:

你猜对了吗?不完全,是吧。在then⾥⾯的回调开始执⾏时,runAsync2()和runAsync3()并没有停⽌,仍旧再执⾏。于是再过1秒后,输

出了他们结束的标志。

这个race有什么⽤呢?使⽤场景还是很多的,⽐如我们可以⽤race给某个异步请求设置超时时间,并且在超时后执⾏相应的操作,代码如

下:

//请求某个图⽚资源

functionrequestImg(){

varp=newPromi(function(resolve,reject){

varimg=newImage();

=function(){

resolve(img);

}

='xxxxxx';

});

returnp;

}

//延时函数,⽤于给请求计时

functiontimeout(){

varp=newPromi(function(resolve,reject){

tTimeout(function(){

reject('图⽚请求超时');

},5000);

});

returnp;

}

Promi

.race([requestImg(),timeout()])

.then(function(results){

(results);

})

.catch(function(reason){

(reason);

});

requestImg函数会异步请求⼀张图⽚,我把地址写为"xxxxxx",所以肯定是⽆法成功请求到的。timeout函数是⼀个延时5秒的异步操作。

我们把这两个返回Promi对象的函数放进race,于是他俩就会赛跑,如果5秒之内图⽚请求成功了,那么遍进⼊then⽅法,执⾏正常的流

程。如果5秒钟图⽚还未成功返回,那么timeout就跑赢了,则进⼊catch,报出“图⽚请求超时”的信息。运⾏结果如下:

总结

ES6Promi的内容就这些吗?是的,能⽤到的基本就这些。

我怎么还见过done、finally、success、fail等,这些是啥?这些并不在Promi标准中,⽽是我们⾃⼰实现的语法糖。

本⽂中所有异步操作均以tTimeout为例⼦,之所以不使⽤ajax是为了避免引起混淆,因为谈起ajax,很多⼈的第⼀反应就是jquery的

ajax,⽽jquery⼜有⾃⼰的Promi实现。如果你理解了原理,就知道使⽤tTimeout和使⽤ajax是⼀样的意思。说起jquery,我不得不

吐槽⼀句,jquery的Promi实现太过垃圾,各种语法糖把⼈都搞蒙了,我认为Promi之所以没有全⾯普及和jquery有很⼤的关系。后⾯

我们会细讲jquery。

本文发布于:2022-11-24 16:45:14,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/90/13039.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:navigational
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图