大佬教程收集整理的这篇文章主要介绍了基于dojo.DeferredList的事件等待机制一例,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
dojo.DeferredList很好地解决了一个事件的触发需要在多个资源上等待的情况。先来回顾一下它的使用:
假设事件doSomething需要两个资源res1和res2同时可用时才能触发,用下面的示例代码来模拟:
function waitForresource(/*String*/resourceName){ var d = new dojo.Deferred(); setTimeout(function(){ d.callBACk(resourcename + " is available"); },1700); return d; } function doSomething(res){ console.log(">>> doSomething"); dojo.forEach(res,function(item,index,array){ console.log(index,item[0],item[1]); }); console.log("<<< doSomething"); console.timeEnd("timer"); } var waitObj1 = waitForresource('res1'); var waitobj2 = waitForresource('res2'); var waitObjects = new dojo.DeferredList([waitObj1,waitobj2]); console.time("timer"); waitObjects.then(doSomething);
下面是运行结果:
>>> doSomething dojo.xd.js (第 14 行) 0 true res1 is available dojo.xd.js (第 14 行) 1 true res2 is available dojo.xd.js (第 14 行) <<< doSomething dojo.xd.js (第 14 行) timer: 1713ms dojo.xd.js (第 14 行)
非常好用。但是...
上述代码为演示目的,集中在一个模块中,所以变量都可以彼此引用。考虑到这样的情况:我们先用dojo.require请求了一个新的模块文件。dojo.ready()可以确保只有在模块加载成功后再执行后面的代码。这个模块又象服务器请求一段数据,比如是对这个模块的配置。
@H_440_4@module.A: dojo.require("newModule"); when (newModule is ready and data is ready) doSomething; newModule: var waitObject = waitForresource(...);如果应用程序有一个全局的单例对象,比如说叫Application,它有一个state状态来跟踪所有需要等待的资源。这样,我们就可以在程序的任意地方向这个对象注册要等待的资源,而在需要等待的资源才能继续执行的地方来判断能否继续。
var State = function(){ var op = this.constructor.prototype; if (!op.registerEvent){ op.registerEvent = function(/*String*/resName,/*dojo.Deferred*/df){ if (!this[resName]){ this[resName] = {}; this[resName]._dfList = []; } this[resName]._dfList.push(df); console.log("%d wait object(s) in the queue [%s]",this[resName]._dfList.length,resName); this[resName]._dl = new dojo.DeferredList(this[resName]._dfList); } } if (!op.ready){ op.ready = function ready(/*String*/resName,/*function*/doSomething){ if (this[resName]._dl){ var destroy = dojo.hitch(this,this._destroy); this[resName]._dl.then(function(res){doSomething(res); destroy(resName)}); }else{ doSomething(); } } } if (!op._destroy){ op._destroy = function(/*String*/resName){ console.log("destroy",resName); this[resName]._dl = null; this[resName]._dfList = []; } } } function waitForresource(/*String*/resourcename,/*Int*/ETA){ var d = new dojo.Deferred(); setTimeout(function(){d.callBACk(resourcename + " is ready");},ETA); return d; } var state = new State(); var d1 = waitForresource("ModuleB",3000); state.registerEvent("resource batch 1",d1); function use(){ state.ready("resource batch 1",function(res){ dojo.forEach(res,item); }); console.log("use: ready to do something"); }); } function use2(){ state.ready("resource batch 2",item); }); console.log("use2: ready to do something"); }); } setTimeout(use,0); d1 = waitForresource("ModuleB",2000); d2 = waitForresource("Data",1000); state.registerEvent("resource batch 2",d1); state.registerEvent("resource batch 2",d2); setTimeout(use2,1500); setTimeout(use2,1500);程序不但考虑了一个事件需要等待多个资源的情况,而且考虑了多个事件需要等待多批资源的情况(尽管Javascript引擎在浏览器中的实现是单线程,但它的事件处理机制,加上setTimeout等机制使得上述第二种情况仍然有可能出现)。每一批资源都关联到一个资源名字,或者用待激活的事件名来命名也可以。
现在,只要将State对象设为全局对象,就可以在任何地方,在为某事件请求资源时注册一个等待事件,在使用资源前通过State.ready(/*String*/resourcename,/*Function*/handler)来进行资源请求完成后的处理。如果是请求数据,则需要处理的数据会保存在handler惟一的参数res中。
参数res在dojo.Deferred的handler中是一个对象,它的值是由Deferred对象当初调用callBACk()函数时传入的。参数res在dojo.DeferredList的handler中是一个数组,每个数组元素具有{/*Boolean*/fired,/*object*/data}这样的结构。这也可由上述代码在firebug中运行的结果中看出来:
结合运行结果作一些分析。首先,跟dojo.Deferred/dojo.DeferredList一样,state.ready()并不能阻塞其后代码运行,只能阻塞传入其中的回调函数的运行,直到所请求的资源可用为止。因此,代码段一开始运行就立刻注册了三个资源请求,分别处于两个不同的队列中。
由于第一批资源要在3秒钟以后才可用,第二批资源最迟不超过2秒钟可用,因此函数use2率先被激活。测试代码中调用了两次use2,但第2次调用时没有任何被阻塞的现象,这也是我们期望的。即如果等待的一批资源一旦可用,那么无论其后对同一批资源无论测试多少次,都不应该被阻塞。同样,destroy也被调用两次,不过第二次实际上并没有任何效果(但也没有副作用)。
以上是大佬教程为你收集整理的基于dojo.DeferredList的事件等待机制一例全部内容,希望文章能够帮你解决基于dojo.DeferredList的事件等待机制一例所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。