如何确保javascript的执行顺序之实战篇.doc
如何确保JAVASCRIPT的执行顺序之实战篇我曾在文章如何在多个页面使用同一个HTML片段续的最后提到JAVASCRIPT顺序执行的特性。虽然现代浏览器可以并行的下载JAVASCRIPT(部分浏览器),但考虑到JAVASCRIPT的依赖关系,他们的执行依然是按照引入顺序进行的。1引言我曾在文章如何在多个页面使用同一个HTML片段续的最后提到JAVASCRIPT顺序执行的特性。虽然现代浏览器可以并行的下载JAVASCRIPT(部分浏览器),但考虑到JAVASCRIPT的依赖关系,他们的执行依然是按照引入顺序进行的。为了更好的测试这个过程,我写了一个简单的HTTP处理程序页面SERVICEASHX,它可以接受两个参数1FILE,需要返回文件的服务器端路径。2DELAY,延迟一定时间后再返回本次HTTP请求(毫秒)。一个典型的页面比如/SERVICEASHXFILEJS/JQUERYUIJSIFSTRINGISNULLOREMPTYCONTEXTREQUEST“DELAY“{DELAYCONVERTTOINT32CONTEXTREQUEST“DELAY“}IFDELAY0{SYSTEMTHREADINGTHREADSLEEP1000}STRINGFILEPATHCONTEXTREQUEST“FILE“TOSTRINGSTRINGFILECONTENTSTRINGEMPTYUSINGSTREAMREADERSRNEWSTREAMREADERCONTEXTSERVERMAPPATHFILEPATH{FILECONTENTSRREADTOEND}IFFILEPATHENDSWITH“JS“{CONTEXTRESPONSECONTENTTYPE“APPLICATION/XJAVASCRIPT“}ELSE{CONTEXTRESPONSECONTENTTYPE“TEXT/PLAIN“}CONTEXTRESPONSEWRITEFILECONTENT}2通过SCRIPT标签直接引入JAVASCRIPT(TEST1HTM)首先我们分析下在标签中顺序引入JAVASCRIPT的情况。TEST1HTM的页面源代码如下复制代码代码如下ALERTTYPEOFJQUERYUI我们分别在各种浏览器中测试这个例子TEST1HTM通过SCRIPT标签直接引入JAVASCRIPTFIREFOX36IE8CHROME10SAFARI4OPERA11可以看出各个主流浏览器的行为一致。虽然JQUERYUI在服务器延迟了2秒钟再返回,但是后引入的内联JAVASCRIPT还是等待了2秒,等前面引入的JAVASCRIPT执行完毕才执行。这也是著名的JAVASCRIPT顺序执行的特性。3通过JAVASCRIPT添加SCRIPT标签(TEST3HTM)我们首先定义一个ADDSCRIPT函数,用来引入外部或者内联JAVASCRIPT。TEST3HTM的页面源代码如下复制代码代码如下FUNCTIONADDSCRIPTURL,INLINE{VARHEADDOCUMENTGETELEMENTSBYTAGNAME“HEAD“0VARSCRIPTDOCUMENTCREATEELEMENTSCRIPTSCRIPTTYPETEXT/JAVASCRIPTIFINLINE{SCRIPTTEXTURL}ELSE{SCRIPTSRCURL}HEADAPPENDCHILDSCRIPT}FUNCTION{ADDSCRIPT/SERVICEASHXFILEJS/JQUERYUIJSADDSCRIPTALERTTYPEOFJQUERYUI,TRUE}我们分别在各种浏览器中测试这个例子TEST3HTM通过JAVASCRIPT添加标签FIREFOX36IE8CHROME10SAFARI4OPERA11可见,通过JAVASCRIPT在DOM加载完毕后再引入外部或者内联JAVASCRIPT时,FIREFOX和OPERA的行为一致,能够确保JAVASCRIPT的执行顺序和引入顺序一致。但是IE8,CHROME,SAFARI却不能保证这个执行顺序。虽然各种浏览器在确保执行顺序方面不尽相同,不过这时的最大好处是多个JAVASCRIPT文件能够并行下载,这在所有浏览器中行为一致。当然这不是这篇文章的主题,可以GOOGLE更多细节。如何解决各个浏览器的不一致性,下面提供了两个解决方案4方案一,如何在动态添加SCRIPT标签时确保执行顺序有时页面逻辑要求我们必须通过上面的方式动态执行JAVASCRIPT,那么如何确保所有浏览器下的执行顺序(目前只有FIREFOX和OPERA确保执行顺序)。其实解决方案很简单,我们为函数执行添加一个COMPLETE的回调函数就行了。下面的TEST4HTM给出了具体的解决方案复制代码代码如下FUNCTIONADDSCRIPTURL,INLINE,CALLBACK{VARHEADDOCUMENTGETELEMENTSBYTAGNAME“HEAD“0VARSCRIPTDOCUMENTCREATEELEMENTSCRIPTSCRIPTTYPETEXT/JAVASCRIPTIFINLINE{SCRIPTTEXTURL}ELSE{SCRIPTSRCURLSCRIPTONLOADSCRIPTONREADYSTATECHANGEFUNCTION{IFSCRIPTREADYSTATE||SCRIPTREADYSTATELOADED||SCRIPTREADYSTATECOMPLETE{IFCALLBACK{CALLBACK}SCRIPTONLOADSCRIPTONREADYSTATECHANGENULL}}}HEADAPPENDCHILDSCRIPTIFINLINE}}FUNCTION{ADDSCRIPT/SERVICEWWWVISA158COMASHXFILEJS/JQUERYUIJS,TRUE}}此时所有浏览器中的行为一致TEST4HTM通过回调函数解决动态添加JAVASCRIPT的顺序问题FIREFOX36IE8CHROME10SAFARI4OPERA115方案二,使用JQUERY的HTML函数动态添加JAVASCRIPTJQUERY的HTML函数用来更新一个DOM片段,我们可以很方便的通过这个函数来动态加载JAVASCRIPT,请看示例TEST2HTM复制代码代码如下FUNCTION{CONTAINERHTMLALERTTYPEOFJQUERYUI}此时,各个浏览器中的行为一致TEST2HTM通过JQUERY的HTML函数解决动态添加JAVASCRIPT的顺序问题FIREFOX36IE8CHROME10SAFARI4OPERA116后记为什么JQUERY的HTML函数能够确保动态加载JAVASCRIPT的执行顺序呢我们知道通过简单的INNERHTML更新DOM节点,是不会让其中的JAVASCRIPT的执行,我们可以简单的把这个例子的源代码改成CONTAINER0INNERHTMLALERTTYPEOFJQUERYUI这种情况下JQUERYUI根本不会加载。那么JQUERY是如果做到的呢我们先来简单回顾下HTML源代码(