你的位置:首页 > 软件开发 > Java > JavaScript异步编程(2)

JavaScript异步编程(2)

发布时间:2015-05-11 12:00:54
原文出处: linkFly 欢迎分享原创到伯乐头条JavaScript当前有众多实现异步编程的方式,最为耀眼的就是ECMAScript 6规范中的Promise对象,它来自于CommonJS小组的努力:Promise/A+规范。研究javascript的异步编 ...

JavaScript异步编程(2)

原文出处: linkFly   欢迎分享原创到伯乐头条

Deferred对象的静态方法 – Deferred.next()源码:

1

我们务必要理清Deferred.next()和Deferred.prototype.next(),这是两种不同的东西:

  • Deferred.next()的职责是压入异步的代码,并立即异步执行的。
  • Deferred.prototype.next()是从上一个Deferred对象链中构建的Deferred。当没有上一个Deferred链的时候,它并不会执行next()中压入的函数,它的执行继承于上一个Deferred触发的事件或自身事件的触发[ call / fail ]。

摘录源码如下:

1

再一次强调,务必搞清楚Deferred.next()和Deferred.prototype.next()。

jsDeferred API

当我第一次知道jsDeferred API有一坨的时候,其实我是,是拒绝的。我跟你讲,我拒绝,因为其实我觉得这根本要不了一坨,但正妹跟我讲,jsDeferred内部会加特技,是假的一坨,是表面看起来一坨。加了特技之后,jsDeferred duang~duang~duang~,很酷,很炫,很酷炫。

jsDeferred的API众多,因为jsDeferred把所有的异步问题都划分到了最小的粒子,这些API相互进行组合则可以完成逆天的异步能力,在后续的API示例中可以看到jsDeferred API组合从而完成强大的异步编程。我们在阅读jsDeferred的API的时候应该时刻思考如果使用ES6的Promise对象又该如何去处理,阅读应该是大脑的盛宴。 貌似没有看到过jsDeferred的详细的中文API文档(原API文档),就这里顺便整理一份简单的出来(虽然它的API已经足够通俗易懂了)。值得一提的是官网的API引导例子非常的生动和实用: Deferred()/new Deferred ()

构造函数(constructor),创建一个Deferred对象。

1

实例方法 Deferred.prototype.next和Deferred.prototype.call

Deferred.prototype.next()构建一个全新的Deferred对象,并为它绑定成功事件处理函数,在没有调用Deferred.prototype.call()之前这个事件处理函数并不会执行。

1

Deferred.prototype.error和Deferred.prototype.fail

Deferred.prototype.error()构建一个全新的Deferred对象,并为它绑定失败事件处理函数,在没有调用Deferred.prototype.fail()之前这个事件处理函数并不会执行。

1

静态方法。Deferred所有的静态方法,都可以使用Deferred.方法名()的方式调用。 Deferred.define(obj, list)

暴露静态方法到obj上,无参的情况下obj是全局对象:侵入性极强,但使用方便。list是一组方法,这组方**同时注册到obj上。

1

 

Deferred.isDeferred(obj)

判断对象obj是否是jsDeferred对象的实例(Deferred对象)。

1

 

Deferred.call(fn[,args]*)

创建一个Deferred实例,并且触发其成功事件。fn是成功后要执行的函数,后续的参数表示传递给fn的参数。

1

 

Deferred.next(fn)

创建一个Deferred实例,并且触发其成功事件。fn是成功后要执行的函数,它等同于只有一个参数的call,即:Deferred.call(fn)

1

 

Deferred.wait(time)

创建一个Deferred实例,并等待time(秒)后触发其成功事件,下面的代码首先弹出”Hello,”,2秒后弹出”World!”。

1

 

Deferred.loop(n, fun)

循环执行n次fun,并将最后一次执行fun()的返回值作为Deferred实例成功事件处理函数的参数,同样loop中循环执行的fun()也是异步的。

1

 

Deferred.parallel(dl[ ,fn]*)

把参数中非Deferred对象均转换为Deferred对象(通过Deferred.next()),然后并行触发dl中的Deferred实例的成功事件。 当所有Deferred对象均调用了成功事件处理函数后,返回的Deferred实例则触发成功事件,并且所有返回值将被封装为数组作为Deferred实例的成功事件处理函数的入参。 parallel()强悍之处在于它的并归处理,它可以将参数中多次的异步最终并归到一起,这一点在JavaScript ajax嵌套中尤为重要:例如同时发送2条ajax请求,最终parallel()会并归这2条ajax返回的结果。

parallel()进行了3次重载:

  • parallel(fn[ ,fn]*):传入Function类型的参数,允许多个
  • parallel(Array):给定一个由Function组成的Array类型的参数
  • parallel(Object):给定一个对象,由对象中所有可枚举的Function构建Deferred

 

下面一张图演示了Deferred.parallel的工作模型,它可以理解为合并了3次ajax请求。 JavaScript异步编程(2)

1

当parallel传递的参数是一个对象的时候,返回值则是一个对象:

1

和jQuery.when()如出一辙。

 

Deferred.earlier(dl[ ,fn]*)

当参数中某一个Deferred对象调用了成功处理函数,则终止参数中其他Deferred对象的触发的成功事件,返回的Deferred实例则触发成功事件,并且那个触发成功事件的函数返回值将作为Deferred实例的成功事件处理函数的入参。 注意:Deferred.earlier()并不会通过Deferred.define(obj)暴露给obj,它只能通过Deferred.earlier()调用。

Deferred.earlier()内部的实现和Deferred.parallel()大同小异,但值得注意的是参数,它接受的是Deferred,而不是parallel()的Function:

  • Deferred.earlier(Deferred[ ,Deferred]*):传入Deferred类型的参数,允许多个
  • Deferred.earlier(Array):给定一个由Deferred组成的Array类型的参数
  • Deferred.earlier(Object):给定一个对象,由对象中所有可枚举的Deferred构建Deferred

 

1

 

Deferred.repeat(n, fun)

循环执行fun方法n次,若fun的执行事件超过20毫秒则先将UI线程的控制权交出,等一会儿再执行下一轮的循环。 自己跑了一下,跑出问题来了…duang…求道友指点下迷津

1

 

Deferred.chain(args)

chain()方法的参数比较独特,可以接受多个参数,参数类型可以是:Function,Object,Array。 chain()方法比较难懂,它是将所有的参数构造出一条Deferred方法链。

例如Function类型的参数:

1

它通过函数名来判断函数:

1

也支持Deferred.parallel()的方式:

1

当然可以组合参数:

1

 

Deferred.connect(funo, options)

将一个函数封装为Deferred对象,其目的是融入现有的异步编程。 注意:Deferred.connect()和Deferred.earlier()方法一样,并不会通过Deferred.define(obj)暴露给obj,它只能通过Deferred.connect()调用。官网使用了setTimeout的例子:

Deferred.connect()有两种重载:

  • Deferred.connect(target,string):把target上名为string指定名称的方法包装为Deferred对象。
  • Deferred.connect(function,Object):Object至少要有一个属性:target。以target为this调用function方法,返回的是包装后的方法,该方法返回Deferred对象。 给包装后的方法传递的参数,会传递给所指定的function。

 

1

 

Deferred.retry(retryCount, funcDeferred[ ,options])

调用retryCount次funcDeffered方法(返回值类型为Deferred),直到触发成功事件或超过尝试次数为止。 options参数是一个对象,{wait:number}指定每次调用等待的秒数。 注意:Deferred.retry()并不会通过Deferred.define(obj)暴露给obj,它只能通过Deferred.retry()调用。

1

从源码这一行可以看到作者重点照顾的是这些方法:

1

其他的方法或许作者也觉得有点勉强吧,在Deferred.define()中默认都没有暴露那些API。

本来就想写jsDeferred的API,结果读完了源码…篇幅原因就不解读源码的,有兴趣的可以在下面的引用链接点过去看源码,不含注释未压缩版源码仅400行左右。

jsDeferred实现简单,代码通俗易懂,而API切割的非常容易上手,理念也容易理解,随着它的知名度提升进而让JavaScript异步编程备受瞩目,在阅读jsDeferred的时候,我总是在想这些前辈们当时苦苦思索走出JavaScript自留地的感觉,从现代的眼光来看,相比Promise,可能jsDeferred的实现甚至于略显青涩。这也让我想起了Robert Nyman前辈最初编写getElementByClassName(),然而在当时看来,足够艳惊世界。 随着JavaScript的兴起,现在的我们多喜欢四处扒来代码匆匆粘贴完成我们大多数的任务,逐渐的丢失了自己思考和挖掘代码的能力。值得庆幸的是JavaScript正在凝结自己的精华,未来迢长路远,与君共勉。 下一篇将会讲解JavaScript异步编程的特性——控制反转。


原标题:JavaScript异步编程(2)

关键词:JavaScript

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。