먼저 Javascript의 로딩과 실행에 대해 이야기하고 싶습니다. 일반적으로 브라우저에는 Javascript 실행에 대한 두 가지 주요 특징이 있습니다. 1) 로드 후 즉시 실행됩니다. 2) 실행 시 페이지의 후속 콘텐츠(페이지 렌더링 및 기타 리소스 다운로드 포함)를 차단합니다. 따라서 여러 js 파일이 도입되면 브라우저의 경우 이러한 js 파일이 직렬로 로드되어 순차적으로 실행됩니다.
자바스크립트는 HTML 문서의 DOM 트리를 조작할 수 있기 때문에 브라우저는 일반적으로 CSS 파일을 병렬로 다운로드하는 것처럼 js 파일을 병렬로 다운로드하지 않습니다. 이는 js 파일의 특수성 때문입니다. 따라서 자바스크립트가 후속 DOM 요소를 작동하려는 경우 기본적으로 브라우저는 객체를 찾을 수 없다는 오류를 보고합니다. Javascript가 실행되면 후속 HTML이 차단되고 DOM 트리에 후속 DOM 노드가 없기 때문입니다. 그래서 프로그램에서 오류를 보고했습니다.
전통적인 방식
그래서 코드에 다음 코드를 작성하면
<scripttype="text/javascript" src="http://coolshell.cn/asyncjs/alert.js"></script>
기본적으로 헤드에 5e0938f6078d2452dc2048f0cba58efa 태그를 document.write한 후에는 다음 작업을 실행할 수 있다고 생각할 수도 있습니다. 이는 맞습니다. 이는 동일한 스크립트 태그의 Javascript 코드에 해당되지만 전체 페이지에서는 여전히 차단됩니다. 다음은 테스트 코드입니다.
<scripttype="text/javascript"language="javascript"> function loadjs(script_filename) { document.write('<' + 'script language="javascript" type="text/javascript"'); document.write(' src="' + script_filename + '">'); document.write('<'+'/script'+'>'); alert("loadjs() exit..."); } var script = 'http://coolshell.cn/asyncjs/alert.js'; loadjs(script); alert("loadjs() finished!"); </script> <scripttype="text/javascript"language="javascript"> alert("another block"); </script>
알림 순서가 어떻게 된다고 생각하시나요? 다양한 브라우저에서 시도해 볼 수 있습니다. 닫으려는 테스트 페이지는 다음과 같습니다. 예 2.
스크립트 지연 및 비동기 속성
IE는 IE6부터 다음과 같은 지연 태그를 지원했습니다.
<scriptdefertype="text/javascript"src="./alert.js"> </script>
IE의 경우 이 태그는 IE가 js 파일을 병렬로 다운로드하고 전체 DOM이 로드될 때까지(DOMContentLoaded) 다중 defer 3f1c4e4b6b16bbbd69b2ee476dc4f83a도 실행됩니다. 가장 중요한 점은 3f1c4e4b6b16bbbd69b2ee476dc4f83a를 defer에 추가한 후에는 후속 DOM 렌더링을 차단하지 않는다는 것입니다. 그러나 이 연기는 IE에만 적용되므로 일반적으로 덜 사용됩니다.
또한 표준 HTML5에는 javascript의 비동기 로딩을 위한 속성인 async가 추가되어 있습니다. 어떤 값을 지정하든 상관없이 js 파일을 비동기적으로 로딩하기 시작합니다. 그러나 async의 비동기 로딩은 "로딩 후 즉시 실행"이라는 군사 규칙을 충실히 구현한다는 심각한 문제가 있습니다. 따라서 페이지 렌더링을 차단하지는 않지만 순서와 타이밍을 제어할 수는 없습니다. 그의 처형. 이 예를 살펴보면서 느낌을 얻을 수 있습니다.
비동기 태그를 지원하는 브라우저는 Firefox 3.6+, Chrome 8.0+, Safari 5.0+, IE 10+입니다. Opera는 아직(여기서부터) 지원하지 않으므로 이 방법은 별로 좋지 않습니다. 왜냐하면 모든 브라우저가 그것을 할 수 있는 것은 아니기 때문입니다.
DOM 방식의 동적 생성
아마도 이 방식이 가장 많이 사용되는 방식일 것입니다.
functionloadjs(script_filename) { varscript = document.createElement('script'); script.setAttribute('type','text/javascript'); script.setAttribute('src', script_filename); script.setAttribute('id','coolshell_script_id'); script_id = document.getElementById('coolshell_script_id'); if(script_id){ document.getElementsByTagName('head')[0].removeChild(script_id); } document.getElementsByTagName('head')[0].appendChild(script); } varscript ='http://coolshell.cn/asyncjs/alert.js'; loadjs(script);
이 방법은 js 파일을 비동기적으로 로드하는 표준 방법이 되었습니다. 이 방법에 대한 데모는 예제 3을 참조하세요. 이 방법은 JSONP에서도 활용되었습니다. 즉, 스크립트의 src에 대해 배경 스크립트(예: PHP)를 지정할 수 있으며, 이 PHP는 매개변수가 json 문자열인 자바스크립트 함수를 반환하고 사전 정의된 자바스크립트 호출을 반환합니다. 기능. 다음 예를 살펴보세요: t.js (이 예는 이전에 Weibo에서 수집한 비동기 ajax 호출의 작은 예입니다.)
요청 시 비동기식으로 js 로드
위의 DOM 메소드 예제는 Javascript의 비동기 로딩 문제를 해결하지만, 우리가 지정한 타이밍에 실행되기를 원하는 문제는 해결하지 못합니다. 따라서 위의 DOM 메소드를 특정 이벤트에만 연결하면 됩니다.
예:
window.load 이벤트에 바인딩 - 예제 4
예제 4와 예 3의 실행 차이점을 비교해야 합니다. 나는 두 예 모두에서, 코드 하이라이팅 자바스크립트를 구체적으로 사용합니다. 코드 하이라이팅 스크립트 실행과 제 Alert.js 실행을 보시면 차이를 아실 겁니다.)
window.load = loadjs("http://coolshell.cn/asyncjs/alert.js")
연결하세요. 특정 이벤트 - 예시 5
<p style="cursor: pointer"onclick="LoadJS()">Click to load alert.js </p>
这个示例很简单了。当你点击某个DOM元素,才会真正载入我们的alert.js。
更多
但是,绑定在某个特定事件上这个事似乎又过了一点,因为只有在点击的时候才会去真正的下载js,这又会太慢了了。好了,到这里,要抛出我们的终极问题——我们想要异步地把js文件下载到用户的本地,但是不执行,仅当在我们想要执行的时候去执行。
要是我们有下面这样的方式就好了:
varscript = document.createElement("script"); script.noexecute =true; script.src ="alert.js"; document.body.appendChild(script); //后面我们可以这么干 script.execute();
可惜的是,这只是一个美丽的梦想,今天我们的Javascript还比较原始,这个“JS梦”还没有实现呢。
所以,我们的程序员只能使用hack的方式来搞。
有的程序员使用了非标准的script的type来cache javascript。如:
<scripttype=cache/scriptsrc="./alert.js"></script>
因为”cache/script”,这个东西根本就不能被浏览器解析,所以浏览器也就不能把alert.js当javascript去执行,但是他又要去下载js文件,所以就可以搞定了。可惜的是,webkit严格符从了HTML的标准——对于这种不认识的东西,直接删除,什么也不干。于是,我们的梦又破了。
所以,我们需要再hack一下,就像N多年前玩preload图片那样,我们可以动用object标签(也可以动用iframe标签),于是我们有下面这样的代码:
functioncachejs(script_filename){ varcache = document.createElement('object'); cache.data = script_filename; cache.id ="coolshell_script_cache_id"; cache.width = 0; cache.height = 0; document.body.appendChild(cache); }
然后,我们在的最后调用一下这个函数。请参看一下相关的示例:示例六
在Chrome下按 Ctrl+Shit+I,切换到network页,你就可以看到下载了alert.js但是没有执行,然后我们再用示例五的方式,因为浏览器端有缓存了,不会再从服务器上下载alert.js了。所以,就能保证执行速度了。
关于这种preload这种东西你应该不会陌生了。你还可以使用Ajax的方式,如:
varxhr =newXMLHttpRequest(); xhr.open('GET','new.js'); xhr.send('');
到这里我就不再多说了,也不给示例了,大家可以自己试试去。
最后再提两个js,一个是ControlJS,一个叫HeadJS,专门用来做异步load javascript文件的。