当前位置: 首页 > 科技观察

JavaScript异步编程中jsdeferred原理解析

时间:2023-03-12 08:51:45 科技观察

1.前言最近在看司徒正妹的《JavaScript框架设计》,看到异步编程的章节介绍了jsdeferred库。我觉得很有趣,花了几天时间研究它。代码,在这里分享。异步编程是写js的一个非常重要的概念,尤其是在处理复杂的应用时,异步编程的技巧是至关重要的。那么我们就来看看这个所谓的里程碑异步编程库吧。2.API源码分析2.1Constructor这里使用了一个安全的构造函数来避免没有new调用构造函数时出错,并提供了两种形式来获取Deferred对象实例。functionDeferred(){return(thisinstanceofDeferred)?this.init():newDeferred();}//方法1varo1=newDeferred();//方法2varo2=Deferred();2.2Deferred.define()这个方法可以包装一个对象,指定对象的方法,或者直接把Deferred对象的方法暴露给全局作用域,这样就可以直接使用了。Deferred.methods=["parallel","wait","next","call","loop","re??peat","chain"];/*@Paramobj赋值对象的属性methodDeferred@Paramlist指定attributemethod*/Deferred.define=function(obj,list){if(!list)list=Deferred.methods;//获取全局作用域的技巧,使用立即执行函数的技巧作为全局作用域if(!obj)obj=(functiongetGlobal(){returnthis})();//将所有属性挂载到objfor(vari=0;ifoo.htmldatav.bar//=>bar.htmldata});3.parallel([fn1,fn2,fn3]).next(function(v){v[0]//fn1执行结果v[1]//fn2执行结果v[3]//fn3执行返回结果});*/varisArray=false;//***formif(arguments.length>1){dl=Array.prototype.slice.call(arguments);isArray=true;//另外两个Form,array,classarray}elseif(Array.isArray&&Array.isArray(dl)||typeofdl.length=="number"){isArray=true;}varret=newDeferred(),//合并结果的延迟对象Instancevalue={},//收集函数执行的结果num=0;//计数器,当为0时,表示所有任务执行完毕//开始遍历,这里使用for-in其实效率不高for(variindl){//防止遍历所有属性,比如toStringif(dl.hasOwnProperty(i)){//使用closure保存变量状态(function(d,i){//使用Deferred.next()启动一个异步Task,执行完成后收集结果if(typeofd=="function")dl[i]=d=Deferred.next(d);d.next(function(v){values[i]=v;if(--num<=0){//计数器为0,表示所有任务已经完成,可以returnif(isArray){//如果是数组,可以把结果转成数组values.length=dl.length;values=Array.prototype.slice.call(values,0);}//调用parallel().next(function(v){}),唤起调用链ret.call(values);}}).error(function(e){ret.fail(e);});num++;//计数器加1})(d[i],i);}}//当计数器为0时,处理那里可能没有参数或非法参数i)){dl[i].cancel();}}};returnret;//返回延迟实例};结合以上知识,我们可以并行使用异步方法,代码如下);});返回;},function(){vard=newDeferred();$.ajax("task2",functionfn2(ret2){d.call(ret2)});return;}).next(functionfn3(ret){ret[0];//=>task1返回的结果ret[1];//=>task2返回的结果});为什么这是可能的?让我们对其进行说明并加深我们的理解。我们通过_fire中的if判断,建立了新的调用链,获得了计数函数的控制权(即并行的--num),从而使得方法异步并行执行。问题解决了!考虑到篇幅,其他的源码分析放在了自己的gitbook上,欢迎交流讨论。参考jsdeferred.jsjsDeferredAPIJavaScript框架设计