defer 및 async 기능은 많은 JavaScript 개발자에게 "익숙하지만 익숙하지 않은" 두 가지 기능이라고 생각됩니다. 문자 그대로 보면 이 두 기능이 "지연 스크립트"입니다. 및 "비동기 스크립트" 효과입니다. 그러나 연기를 예로 들면 개발자는 연기 기능이 있는 스크립트의 실행이 언제 지연되는지, 내부 스크립트와 외부 스크립트가 연기 후 스크립트를 지원할 수 있는지 여부와 같은 일부 세부 사항에 익숙하지 않을 수 있습니다. 지연 실행 외에 특별한 기능은 무엇입니까? 이 기사는 개발자가 이 두 기능을 더 잘 익히는 데 도움이 되기를 바라며 기존 기사와 MDN 문서의 두 기능에 대한 설명을 결합하여 지연 및 비동기에 대한 보다 포괄적인 연구와 요약을 수행합니다.
1 소개
"브라우저 환경에서 JavaScript 스크립트 로드 및 실행 분석: 코드 실행 순서"에서 JavaScript 코드를 실행하면 페이지의 구문 분석 및 렌더링과 다른 리소스의 다운로드가 차단된다고 언급했습니다. 물론 JavaScript는 단일 스레드 언어이기 때문에 일반적인 상황에서는 페이지의 JavaScript 코드가 위에서 아래로 순서대로만 실행될 수 있습니다. 브라우저 환경에서의 스크립트 로딩 및 실행 "실행 순서 "에서 분석한 것처럼 document.write를 통해 스크립트를 입력하거나 동적 스크립트 기술을 통해 스크립트를 도입하는 경우와 같은 경우에는 JavaScript 코드의 실행 순서가 반드시 위에서 아래로 엄격한 순서를 따를 필요는 없습니다. 지연 및 비동기도 우리가 "비정상적인 상황"이라고 부르는 것입니다.
2가지 연기 기능
2.1 defer 스크립트 실행 시기에 대해
2.2 브라우저 지원 연기
연기 기능에 대한 브라우저 지원을 살펴보겠습니다.
IE9 이하 브라우저에는 버그가 있는데, 이에 대해서는 추후 DEMO에서 자세히 설명하겠습니다.
2.3 DEMO: 연기 기능의 기능 검증
연기 속성의 기능을 확인하기 위해 "스크립트 연기 속성"에서 Olivier Rochard가 사용한 방법을 모방합니다.
먼저 6개의 외부 스크립트를 준비했습니다.
1.js:
test = "나는 외부 스크립트 n입니다."
2.js
test = "나는 신체 외부 스크립트 n입니다"
3.js
test = "저는 하단 외부 스크립트 n입니다"
defer1.js
test = "나는 헤드 외부 지연 스크립트 n입니다"
defer2.js
test = "나는 신체 외부 지연 스크립트 n입니다"
defer3.js
test = "저는 하단 외부 지연 스크립트 n입니다"
HTML의 코드는 다음과 같습니다.
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>defer attribute test</title> <script src="http://lib.sinaapp.com/js/jquery/1.9.1/jquery-1.9.1.min.js"></script> <script type="text/javascript">var test = "";</script> <script src="defer1.js" type="text/javascript" defer="defer"></script> <script src="1.js" type="text/javascript"></script> <script defer="defer"> test += "我是head延迟内部脚本\n"; </script> <script> test += "我是head内部脚本\n"; </script> </head> <body> <button id="test">点击一下</button> <script src="defer2.js" type="text/javascript" defer="defer"></script> <script src="2.js" type="text/javascript"></script> </body> <script src="defer3.js" type="text/javascript" defer="defer"></script> <script src="3.js" type="text/javascript"></script> <script> $(function(){ test += "我是DOMContentLoaded里面的脚本 "; }) window.onload = function(){ test += "我是window.onload里面的脚本 "; var button = document.getElementById("test"); button.onclick = function(){ alert(test); } } </script> </html>
코드에서는 DOMContentLoaded 이벤트 구현을 용이하게 하기 위해 jQuery를 도입했습니다(나중에 호환되는 DOMContentLoaded를 직접 구현하는 방법을 소개할 예정입니다). 그런 다음 헤드, 바디 내부 및 외부에 지연 스크립트를 도입했습니다. 스크립트의 본문과 일반 스크립트를 살펴보고, 전역 문자열을 통해 각 코드의 실행 상태를 기록합니다. 각 브라우저의 실행 결과를 살펴보겠습니다.
IE7 | IE9 | IE10 | 크롬 | 파이어폭스 | ||||||||||
저는 외부 스크립트 책임자입니다
|
저는 외부 스크립트 책임자입니다 저는 내부 스크립트 책임자입니다 나는 신체 외부 스크립트입니다 저는 하단 외부 스크립트입니다 저는 외부 지연 스크립트를 맡고 있습니다 저는 헤드 딜레이 내부 스크립트입니다 나는 신체 외부 지연 스크립트 저는 하단 외부 지연 스크립트입니다 나는 DOMContentLoaded의 스크립트입니다 저는 window.onload의 스크립트입니다 | 저는 외부 스크립트 책임자입니다 내부 스크립트가 너무 지연되었습니다 저는 내부 스크립트 책임자입니다 나는 신체 외부 스크립트입니다 저는 하단 외부 스크립트입니다 저는 외부 지연 스크립트를 맡고 있습니다 나는 신체 외부 지연 스크립트 저는 하단 외부 지연 스크립트입니다 나는 DOMContentLoaded의 스크립트입니다 저는 window.onload의 스크립트입니다 | 저는 외부 스크립트 책임자입니다 내부 스크립트가 너무 지연되었습니다 저는 내부 스크립트 책임자입니다 나는 신체 외부 스크립트입니다 저는 하단 외부 스크립트입니다 저는 외부 지연 스크립트를 맡고 있습니다 나는 신체 외부 지연 스크립트 저는 하단 외부 지연 스크립트입니다 나는 DOMContentLoaded의 스크립트입니다 저는 window.onload의 스크립트입니다 |
从输出的结果中我们可以确定,只有IE9及以下浏览器支持内部延迟脚本,并且defer后的脚本都会在DOMContentLoaded事件之前触发,因此也是会堵塞DOMContentLoaded事件的。
2.4 DEMO:IE0f630a08ba48c70580451c5807d38ff4我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
document.body.innerHTML += "7a6bc4f2a125532aca32e87dac970576我是后来加入的16b28748ea4df4d9c2150843fecfba68";
alert("我是第1个脚本");
2.js
alert("我是第2个脚本");
修改HMTL中的代码为:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>defer bug in IE=9 test</title> <script src="1.js" type="text/javascript" defer="defer"></script> <script src="2.js" type="text/javascript" defer="defer"></script> </head> <body> </body> </html>
正常情况下,浏览器中弹出框的顺序肯定是:我是第1个脚本-》我是第2个脚本,然而在IE77f5db5c498cd8790c183e49397570fd 요소가 defer 및 async 속성을 모두 정의하는 경우 비동기로 처리됩니다(참고: 비동기를 지원하지 않는 브라우저는 비동기 속성을 직접 무시합니다)
[2] 3f1c4e4b6b16bbbd69b2ee476dc4f83a 요소가 defer만 정의하는 경우 지연된 스크립트로 처리됩니다.
[3] 3f1c4e4b6b16bbbd69b2ee476dc4f83a 요소가 defer 또는 async를 정의하지 않으면 정상적으로 처리됩니다. 즉, 스크립트가 즉시 로드되고 실행됩니다.