JQuery의 여러 플러그인, 사용자 정의 위젯 및 기타 라이브러리를 사용하고 있습니다. 결과적으로 여러 .js 및 .css 파일이 있습니다. 로드하는 데 시간이 좀 걸리기 때문에 내 사이트에 대한 로더를 만들어야합니다. 다음을 모두 가져 오기 전에 로더를 표시 할 수 있으면 좋을 것입니다.
<script type="text/javascript" src="js/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="js/myFunctions.js"></script>
<link type="text/css" href="css/main.css" rel="stylesheet" />
...
....
etc
JavaScript 라이브러리를 비동기 적으로 가져올 수있는 몇 가지 자습서를 찾았습니다. 예를 들어 다음과 같이 할 수 있습니다.
(function () {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'js/jquery-ui-1.8.16.custom.min.js';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
})();
어떤 이유로 내 모든 파일에 대해 동일한 작업을 수행하면 페이지가 작동하지 않습니다. 문제가있는 곳을 찾으려고 오랫동안 노력했지만 찾을 수 없습니다. 처음에는 일부 자바 스크립트 기능이 다른 기능에 의존하기 때문일 것이라고 생각했습니다. 그러나 하나가 완료되었을 때 시간 초과 기능을 사용하여 올바른 순서로로드했습니다. 다음 작업을 진행했는데 페이지가 여전히 이상하게 작동합니다. 예를 들어 링크 등을 클릭 할 수 없습니다. 애니메이션은 여전히 작동합니다.
어쨌든
제가 생각한 것은 다음과 같습니다. 브라우저에는 캐시가 있기 때문에 처음으로 페이지를로드하는 데 시간이 오래 걸리고 다음 번에는 빠릅니다. 그래서 제가 생각하는 것은 index.html 페이지를이 모든 파일을 비동기 적으로로드하는 페이지로 바꾸는 것입니다. ajax가 모든 파일을로드하면 내가 사용할 페이지로 리디렉션됩니다. 해당 페이지를 사용할 때 파일이 브라우저의 캐시에 포함되어야하므로로드하는 데 오래 걸리지 않아야합니다. 내 색인 페이지 (.js 및 .css 파일이 비동기 적으로로드되는 페이지)에서 오류가 발생해도 상관 없습니다. 완료되면 로더를 표시하고 페이지를 리디렉션합니다.
이 아이디어가 좋은 대안입니까? 또는 비동기 메서드를 계속 구현해야합니까?
편집하다
모든 비동기를로드하는 방법은 다음과 같습니다.
importScripts();
function importScripts()
{
//import: jquery-ui-1.8.16.custom.min.js
getContent("js/jquery-1.6.2.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
//s.async = true;
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext1,1);
});
//import: jquery-ui-1.8.16.custom.min.js
function insertNext1()
{
getContent("js/jquery-ui-1.8.16.custom.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext2,1);
});
}
//import: jquery-ui-1.8.16.custom.css
function insertNext2()
{
getContent("css/custom-theme/jquery-ui-1.8.16.custom.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext3,1);
});
}
//import: main.css
function insertNext3()
{
getContent("css/main.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext4,1);
});
}
//import: jquery.imgpreload.min.js
function insertNext4()
{
getContent("js/farinspace/jquery.imgpreload.min.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext5,1);
});
}
//import: marquee.js
function insertNext5()
{
getContent("js/marquee.js",function (code) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext6,1);
});
}
//import: marquee.css
function insertNext6()
{
getContent("css/marquee.css",function (code) {
var s = document.createElement('link');
s.type = 'text/css';
s.rel ="stylesheet";
s.innerHTML=code;
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(insertNext,1);
});
}
function insertNext()
{
setTimeout(pageReadyMan,10);
}
}
// get the content of url and pass that content to specified function
function getContent( url, callBackFunction )
{
// attempt to create the XMLHttpRequest and make the request
try
{
var asyncRequest; // variable to hold XMLHttpRequest object
asyncRequest = new XMLHttpRequest(); // create request object
// register event handler
asyncRequest.onreadystatechange = function(){
stateChange(asyncRequest, callBackFunction);
}
asyncRequest.open( 'GET', url, true ); // prepare the request
asyncRequest.send( null ); // send the request
} // end try
catch ( exception )
{
alert( 'Request failed.' );
} // end catch
} // end function getContent
// call function whith content when ready
function stateChange(asyncRequest, callBackFunction)
{
if ( asyncRequest.readyState == 4 && asyncRequest.status == 200 )
{
callBackFunction(asyncRequest.responseText);
} // end if
} // end function stateChange
그리고 이상한 부분은 모든 스타일의 작업과 모든 자바 스크립트 함수입니다. 그래도 페이지가 멈췄습니다 …
답변
비동기 로딩을위한 몇 가지 솔루션 :
//this function will work cross-browser for loading scripts asynchronously
function loadScript(src, callback)
{
var s,
r,
t;
r = false;
s = document.createElement('script');
s.type = 'text/javascript';
s.src = src;
s.onload = s.onreadystatechange = function() {
//console.log( this.readyState ); //uncomment this line to see which ready states are called.
if ( !r && (!this.readyState || this.readyState == 'complete') )
{
r = true;
callback();
}
};
t = document.getElementsByTagName('script')[0];
t.parentNode.insertBefore(s, t);
}
페이지에 이미 jQuery가있는 경우 다음을 사용하십시오.
$.getScript(url, successCallback)
*
또한 문서가로드되기 전에 스크립트가로드 / 실행될 document.ready
수 있습니다. 즉, 이벤트가 요소에 바인딩 될 수 있기 전에 기다려야합니다 .
코드를 보지 않고는 문제가 무엇인지 구체적으로 말할 수 없습니다.
가장 간단한 해결책은 모든 스크립트를 페이지 하단에 인라인으로 유지하는 것입니다. 이렇게하면 실행 중에 HTML 콘텐츠로드를 차단하지 않습니다. 또한 필요한 각 스크립트를 비동기 적으로로드해야하는 문제를 방지합니다.
어떤 종류의 더 큰 스크립트를 필요로하는 항상 사용되지 않는 특히 멋진 상호 작용이있는 경우 필요할 때까지 특정 스크립트를로드하지 않는 것이 유용 할 수 있습니다 (지연로드).
*로 로드 된 스크립트 $.getScript
는 캐시되지 않을 가능성이 높습니다.
Promise
객체 와 같은 최신 기능을 사용할 수있는 사람이라면 누구나 loadScript
기능이 훨씬 간단 해졌습니다.
function loadScript(src) {
return new Promise(function (resolve, reject) {
var s;
s = document.createElement('script');
s.src = src;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
}
callback
반환 된 promise가 콜백을 처리하므로이 버전은 더 이상 인수를 허용하지 않습니다 . 이전에는이었을 loadScript(src, callback)
것 loadScript(src).then(callback)
입니다.
이것은 실패를 감지하고 처리 할 수 있다는 추가 보너스가 있습니다.
loadScript(cdnSource)
.catch(loadScript.bind(null, localSource))
.then(successCallback, failureCallback);
… 그리고 CDN 중단을 우아하게 처리합니다.
답변
HTML5의 새로운 ‘async’속성이 트릭을 수행합니다. IE에 관심이 있다면 대부분의 브라우저에서 ‘지연’도 지원됩니다.
async-HTML
<script async src="siteScript.js" onload="myInit()"></script>
지연-HTML
<script defer src="siteScript.js" onload="myInit()"></script>
새 애드 센스 광고 단위 코드를 분석하는 동안 속성과 검색 결과를 발견했습니다. http://davidwalsh.name/html5-async
답변
로드가 완료된 모든 스크립트가 index2.html에서 동일한 라이브러리를 사용하는 index2.html로 페이지를 리디렉션 할 때 스크립트를 비동기 적으로로드했습니다 (html 5에는 해당 기능이 있음). 페이지가 index2.html로 리디렉션되면 브라우저에 캐시가 있기 때문에 index2.html은 페이지를로드하는 데 필요한 모든 것이 있으므로 1 초 이내에로드됩니다. 내 index.html 페이지에서 브라우저가 해당 이미지를 캐시에 배치 할 수 있도록 사용하려는 이미지도로드합니다. 그래서 내 index.html은 다음과 같습니다.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Project Management</title>
<!-- the purpose of this page is to load all the scripts on the browsers cache so that pages can load fast from now on -->
<script type="text/javascript">
function stylesheet(url) {
var s = document.createElement('link');
s.type = 'text/css';
s.async = true;
s.src = url;
var x = document.getElementsByTagName('head')[0];
x.appendChild(s);
}
function script(url) {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = url;
var x = document.getElementsByTagName('head')[0];
x.appendChild(s);
}
//load scritps to the catche of browser
(function () {
stylesheet('css/custom-theme/jquery-ui-1.8.16.custom.css');
stylesheet('css/main.css');
stylesheet('css/marquee.css');
stylesheet('css/mainTable.css');
script('js/jquery-ui-1.8.16.custom.min.js');
script('js/jquery-1.6.2.min.js');
script('js/myFunctions.js');
script('js/farinspace/jquery.imgpreload.min.js');
script('js/marquee.js');
})();
</script>
<script type="text/javascript">
// once the page is loaded go to index2.html
window.onload = function () {
document.location = "index2.html";
}
</script>
</head>
<body>
<div id="cover" style="position:fixed; left:0px; top:0px; width:100%; height:100%; background-color:Black; z-index:100;">Loading</div>
<img src="images/home/background.png" />
<img src="images/home/3.png"/>
<img src="images/home/6.jpg"/>
<img src="images/home/4.png"/>
<img src="images/home/5.png"/>
<img src="images/home/8.jpg"/>
<img src="images/home/9.jpg"/>
<img src="images/logo.png"/>
<img src="images/logo.png"/>
<img src="images/theme/contentBorder.png"/>
</body>
</html>
이것에 대한 또 다른 좋은 점은 페이지에 로더를 배치 할 수 있고 페이지로드가 완료되면 로더가 사라지고 밀리 초 내에 새 페이지가 실행된다는 것입니다.
답변
Google의 예
<script type="text/javascript">
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js?onload=onLoadCallback';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
답변
몇 가지 참고 사항 :
s.async = true
HTML5 doctype에는 그다지 정확하지 않습니다.s.async = 'async'
(실제로true
는 바로 아래 주석 에서 지적한 amn 덕분에 is correct 사용 )- 시간 제한을 사용하여 주문을 제어하는 것은 그리 좋지 않고 안전하지 않으며 모든 시간 제한의 합계와 동일하게로드 시간을 훨씬 더 크게 만듭니다!
최근에 파일을 비동기식으로로드하는 이유가 있지만 순서대로 예제보다 기능 중심적인 방법을 권장합니다 ( console.log
프로덕션 사용을 위해 제거 :)).
(function() {
var prot = ("https:"===document.location.protocol?"https://":"http://");
var scripts = [
"path/to/first.js",
"path/to/second.js",
"path/to/third.js"
];
function completed() { console.log('completed'); } // FIXME: remove logs
function checkStateAndCall(path, callback) {
var _success = false;
return function() {
if (!_success && (!this.readyState || (this.readyState == 'complete'))) {
_success = true;
console.log(path, 'is ready'); // FIXME: remove logs
callback();
}
};
}
function asyncLoadScripts(files) {
function loadNext() { // chain element
if (!files.length) completed();
var path = files.shift();
var scriptElm = document.createElement('script');
scriptElm.type = 'text/javascript';
scriptElm.async = true;
scriptElm.src = prot+path;
scriptElm.onload = scriptElm.onreadystatechange = \
checkStateAndCall(path, loadNext); // load next file in chain when
// this one will be ready
var headElm = document.head || document.getElementsByTagName('head')[0];
headElm.appendChild(scriptElm);
}
loadNext(); // start a chain
}
asyncLoadScripts(scripts);
})();
답변
HTML5 덕분에 이제 태그에 “async”를 추가하여 비동기 적으로로드 할 스크립트를 선언 할 수 있습니다.
<script async>...</script>
참고 : async 속성은 외부 스크립트 전용이며 src 속성이있는 경우에만 사용해야합니다.
참고 : 외부 스크립트를 실행할 수있는 방법에는 여러 가지가 있습니다.
- 비동기가있는 경우 : 스크립트가 페이지의 나머지 부분과 비동기 적으로 실행됩니다 (페이지가 구문 분석을 계속하는 동안 스크립트가 실행 됨).
- async가없고 defer가있는 경우 : 페이지가 구문 분석을 완료하면 스크립트가 실행됩니다.
- 비동기 또는 지연이없는 경우 : 브라우저가 페이지를 계속 구문 분석하기 전에 스크립트를 가져 와서 즉시 실행합니다.
답변
콜백이 있는지 확인하고 인수 전달을 허용하여 zzzzBov의 답변을 완료합니다.
function loadScript(src, callback, args) {
var s, r, t;
r = false;
s = document.createElement('script');
s.type = 'text/javascript';
s.src = src;
if (typeof(callback) === 'function') {
s.onload = s.onreadystatechange = function() {
if (!r && (!this.readyState || this.readyState === 'complete')) {
r = true;
callback.apply(args);
}
};
};
t = document.getElementsByTagName('script')[0];
t.parent.insertBefore(s, t);
}