jquery가로드 될 때까지 스크립트 실행을 대기시키는 방법


106

페이지가 너무 빨리로드되는 문제가있어 jquery가 후속 스크립트에서 호출되기 전에로드가 완료되지 않았습니다. jquery의 존재를 확인하고 존재하지 않는 경우 잠시 기다렸다가 다시 시도하는 방법이 있습니까?


아래 답변 / 댓글에 대한 응답으로 일부 마크 업을 게시하고 있습니다.

상황 ... asp.net masterpage 및 childpage.

마스터 페이지에는 jquery에 대한 참조가 있습니다. 그런 다음 콘텐츠 페이지에 페이지 별 스크립트에 대한 참조가 있습니다. 페이지 특정 스크립트가로드 될 때 "$가 정의되지 않았습니다"라고 불평합니다.

마크 업의 여러 지점에 경고를 표시하여 실행되는 순서를 확인하고 다음 순서로 실행되는지 확인했습니다.

  1. 마스터 페이지 헤더.
  2. 하위 페이지 콘텐츠 블록 1 (마스터 페이지의 헤드 내부에 있지만 마스터 페이지 스크립트가 호출 된 후)
  3. 하위 페이지 콘텐츠 블록 2.

다음은 마스터 페이지 상단의 마크 업입니다.

<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs" Inherits="SiteMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Reporting Portal</title>
    <link href="~/Styles/site.css" rel="stylesheet" type="text/css" />
    <link href="~/Styles/red/red.css" rel="stylesheet" type="text/css" />
    <script type="text/Scripts" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
    <script type="text/Scripts" language="javascript" src="../Scripts/jquery.dropdownPlain.js"></script>
    <script type="text/Scripts" language="javascript" src="../Scripts/facebox.js"></script>
    <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>

그런 다음 마스터 페이지의 본문에 추가 ContentPlaceHolder가 있습니다.

 <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
                </asp:ContentPlaceHolder>

하위 페이지에서 다음과 같이 보입니다.

<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Dashboard.aspx.cs" Inherits="Data.Dashboard" %>
<%@ Register src="../userControls/ucDropdownMenu.ascx" tagname="ucDropdownMenu" tagprefix="uc1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    <link rel="stylesheet" type="text/css" href="../Styles/paserMap.css" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
***CONTENT HERE***
    <script src="../Scripts/Dashboard.js" type="text/javascript"></script>
</asp:Content>

다음은 "../Script/Dashboard.js"파일의 내용입니다.

    $(document).ready(function () {

    $('.tgl:first').show(); // Show the first div

    //Description: East panel parent tab navigation
    $('.tabNav label').click(function () {
        $('.tabNav li').removeClass('active')
        $(this).parent().addClass('active');

        var index = $(this).parent('li').index();
        var divToggle = $('.ui-layout-content').children('div.tgl');

        //hide all subToggle divs
        divToggle.hide();
        divToggle.eq(index).show();
    });

});

4
당신은 사용하고 $(document).ready(function(){...});있습니까?
rownage 2011 년

간단한 <script src="...">태그가있는 스크립트를로드하는 경우 에는 불가능합니다. RequireJS 또는 LABjs와 같은 것을 사용하고 있습니까?
Pointy 2011-09-20

$(document).ready()또는 에서 후속 스크립트를 실행하고 $(window).load()있습니까? 예를 볼 수 있을까요?
John Hartsock 2011 년

1
@AmandaMyer 지금, 문서 준비 사용에 대한 모든 제안을 무시하십시오. 이미 그렇게하고 있기 때문입니다.하지만 MIME 유형이 동기식으로로드되지 않는 원인이 될 것입니다
Sander

2
변경 시도 type="text/Scripts"type="text/javascript", 또는 모두 함께 더 이상 필요하지 않은 것 없애도 제거 language="javascript. 시도해 볼 수도 있습니다.
Jack

답변:


11

편집하다

스크립트 태그에 올바른 유형을 시도해 주시겠습니까? 나는 당신 text/Scripts이 자바 스크립트에 적합한 MIME 유형이 아닌 을 사용하는 것을 봅니다 .

이것을 사용하십시오 :

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> 
<script type="text/javascript" src="../Scripts/jquery.dropdownPlain.js"></script>
<script type="text/javascript" src="../Scripts/facebox.js"></script>

편집 종료

또는 자바 스크립트 코드의 로더 인 require.js 를 살펴볼 수 있습니다 .

프로젝트에 따라 다소 과도 할 수 있습니다.


204

파티에 늦고 Briguy37의 질문과 유사하지만 향후 참조를 위해 다음 방법을 사용하고 jQuery가로드 될 때까지 연기하려는 함수를 전달합니다.

function defer(method) {
    if (window.jQuery) {
        method();
    } else {
        setTimeout(function() { defer(method) }, 50);
    }
}

window.jQuery종료하고 호출 할 때까지 50ms마다 지연 메서드를 재귀 적으로 호출 합니다.method()

익명 함수의 예 :

defer(function () {
    alert("jQuery is now loaded");
});

2
이것은 나를 위해 작동하지 않았습니다. 메서드 내에서 $가 정의되지 않았습니다 ... 아직 이유가 확실하지 않습니다.
Aaron Lifshin

이것은 Adobe Muse에서 다른 사람이 디자인 한 사이트에서 일부 사용자 정의 코드를 작업 할 수있는 좋은 솔루션이었습니다.
Buggabill

@gidim 루프가 아닌 타이머이기 때문에 그렇지 않습니다. 그러나 사용자가 페이지에 머무르는 한 계속 실행됩니다.
Micros

스크립트의 로딩 순서를 조사하는 것이 좋습니다. scriptjQuery를로드 하는 태그에 defer속성 이있는 경우 코드 정의 스크립트 순서에도 불구하고 나중에로드되지 않아 문제가 발생 한다는 것을 발견했습니다 .
ADTC

19

defer 속성을 사용하여 실제로 마지막에 스크립트를로드 할 수 있습니다.

<script type='text/javascript' src='myscript.js' defer='defer'></script>

그러나 일반적으로 스크립트를 올바른 순서로로드하면 트릭을 수행 할 수 있으므로 자신의 스크립트 앞에 jquery를 포함해야합니다.

코드가 별도의 js 파일이 아니라 페이지에있는 경우 문서가 준비된 후에 만 ​​스크립트를 실행해야하고 다음과 같이 코드를 캡슐화해야합니다.

$(function(){
//here goes your code
});

당신은 하나의 종속성이 긴 이것은 괜찮
기욤 한꺼번에

17

Darbio의 지연 방법이 더 유연하지만이를 수행하는 또 다른 방법입니다.

(function() {
  var nTimer = setInterval(function() {
    if (window.jQuery) {
      // Do something with jQuery
      clearInterval(nTimer);
    }
  }, 100);
})();

16

가장 쉽고 안전한 방법은 다음과 같이 사용하는 것입니다.

var waitForJQuery = setInterval(function () {
    if (typeof $ != 'undefined') {

        // place your code here.

        clearInterval(waitForJQuery);
    }
}, 10);

2
Genius 솔루션. 감사합니다
Diego Fortes 2018 년

13

onload 이벤트를 시도 할 수 있습니다. 모든 스크립트가로드되면 발생합니다.

window.onload = function () {
   //jquery ready for use here
}

그러나 window.onload가 사용하는 다른 스크립트를 재정의 할 수 있음을 명심하십시오.


이 작동하지만 JQuery와 페이지의 모양을 변경하는 경우 당신은 아마 스타일이 적용되지 않은 내용의 플래시를 볼 수
마태 복음 잠금을

1
다른 스크립트를 재정의하지 않도록 이벤트 리스너를 추가 할 수 있습니다. stackoverflow.com/a/15564394/32453 FWIW '
rogerdpack

@rogerdpack은 동의합니다. 더 나은 솔루션입니다.
Nigrimmist

10

제안 된 솔루션은 비동기 코드를 염두에두고 만 작동한다는 것을 발견했습니다. 두 경우 모두 작동하는 버전은 다음과 같습니다.

document.addEventListener('DOMContentLoaded', function load() {
    if (!window.jQuery) return setTimeout(load, 50);
    //your synchronous or asynchronous jQuery-related code
}, false);

감사합니다.로드시 한 번 확인하고 50ms마다 폴백 시작으로 만 루프를 시작하는 것이 상위 투표 답변과 같이 setInterval로 루프하는 것보다 훨씬 낫습니다. 가장 좋은 경우에는 상위 답변의 평균 25ms 대신 0ms 지연이 있습니다.
Luc

멋지고 우아함- load함수 를 전달하는 방법이 마음에 들지만 setTimeout.
Nemesarial

6

일반적인 문제입니다. 멋진 PHP 템플릿 엔진을 사용한다고 가정하면 기본 레이아웃이 있습니다.

HEADER
BODY ==> dynamic CONTENT/PAGE
FOOTER

물론 페이지 하단에 자바 스크립트를로드하는 것이 더 나은 곳에서 읽었으므로 동적 콘텐츠는 누가 jQuery (또는 $)인지 알지 못합니다.

또한 작은 Javascript를 인라인하는 것이 좋은 곳에서 읽었으므로 페이지에 jQuery가 필요하다고 상상해보십시오. baboom, $가 정의되지 않았습니다 (.. 아직 ^^).

Facebook이 제공하는 솔루션이 마음에 듭니다.

window.fbAsyncInit = function() { alert('FB is ready !'); }

따라서 게으른 프로그래머 (좋은 프로그래머라고 말해야합니다 ^^)로서 동등한 것을 사용할 수 있습니다 (페이지 내에서).

window.jqReady = function() {}

그리고 레이아웃 하단에 jQuery가 포함시킨 후

if (window.hasOwnProperty('jqReady')) $(function() {window.jqReady();});

감사! 그것이 바로 제가 직면 한 경우입니다.
KumZ

또는 jquery로드를 맨 위로 이동하십시오. :) stackoverflow.com/a/11012073/32453
rogerdpack

5

"대기"(보통를 사용하여 수행됨 setTimeout) 대신 창 자체에서 jQuery 객체를 정의하여 이에 의존하는 코드를 실행하는 후크로 사용할 수도 있습니다. 이것은를 사용하여 정의 된 속성 정의를 통해 달성 할 수 Object.defineProperty있습니다.

(function(){
  var _jQuery;
  Object.defineProperty(window, 'jQuery', {
    get: function() { return _jQuery; },
    set: function($) {
      _jQuery = $;

      // put code or call to function that uses jQuery here

    }
  });
})();

이것은 jQuery가 실제로 창 속성을 정의한 경우 모호하게 유용 할 것이지만 그렇지 않은 것 같습니까?
Jim

실제로 속성을 설정하지는 않지만 전역 범위 (예 window.jQuery:)에서 jQuery변수를 정의하여 값으로 설정 합니다 window. 그러면 코드에 정의 된 창 개체에 대한 속성 설정 기능이 트리거됩니다.
Protector one

이 코드가 실행되기 전에 jQuery 속성이 정의되면 작동하지 않습니다. 즉,이 코드가로드되기 전에 지연된 jquery.js가로드되는 경우. 한 가지 해결책은 지연된 jquery.js를 이전 </body>대신 앞에 두는 것입니다</head>
user36388

@user : jQuery (지연 또는 기타)가로드되기 전에 코드를 실행하면됩니다. 로드하는 위치는 중요하지 않습니다. 내 코드 조각이 그 앞에옵니다.
수호자 하나

1
이것은 문서에 jQuery를 포함하기 전에 이것을 사용하는 스크립트를 보장 할 수 있다면 매우 유용합니다. 위의 반복 접근 방식의 비 효율성 또는 경쟁 사례 시나리오도 없습니다.
RedYetiCo

4

사용하다:

$(document).ready(function() {
    // put all your jQuery goodness in here.
});

자세한 내용은 http://www.learningjquery.com/2006/09/introducing-document-ready 를 확인하십시오 .

참고 : JQuery 라이브러리에 대한 스크립트 가져 오기가이 호출 위에있는 한 작동합니다.

최신 정보:

어떤 이유로 코드가 동기식으로로드되지 않는 경우 ( 내가 본 적이 없지만 아래 주석에서 가능할 수 있음 ) 다음과 같이 코드를 작성할 수 있습니다.

function yourFunctionToRun(){
    //Your JQuery goodness here
}

function runYourFunctionWhenJQueryIsLoaded() {
    if (window.$){
        //possibly some other JQuery checks to make sure that everything is loaded here

        yourFunctionToRun();
    } else {
        setTimeout(runYourFunctionWhenJQueryIsLoaded, 50);
    }
}

runYourFunctionWhenJQueryIsLoaded();

6
이 대기는 jquery가로드 될 때까지가 아니라 DOM이 준비 될 때까지입니다. 그는 아마 CDN에서 2 개 스크립트 파일 1이 (구글에서 JQuery와 로컬 플러그인) 1이 다른보다 먼저로드 .... 플러그인이 빠르게 JQuery와 자체보다로드되면,이 문제를 해결하지 않는 코드
샌더

2
나는 당신과 동의하지 않습니다 @Sander 이것은 로딩이 동기로 작동해야합니다
malko

당신이 옳습니다. 다른 도메인에서 온 경우 비동기로로드된다는 가정은 완전히 잘못되었습니다! 실례합니다
Sander

jquery를 사용할 수없는 경우 예외가 발생하여 else 문에 들어 가지 않게됩니다. 시도하고 잡아야 할 것 같아요.
샘 Stoelinga

@SamStoelinga : 감사합니다. 이제이 문제가 해결되어야합니다.
Briguy37

3

나는 인터벌을 좋아하지 않는다. jquery 또는 실제로 연기하고 싶을 때 일반적으로 다음과 같이 진행됩니다.

시작 :

<html>
 <head>
  <script>var $d=[];var $=(n)=>{$d.push(n)}</script>
 </head>

그때:

 <body>
  <div id="thediv"></div>

  <script>
    $(function(){
       $('#thediv').html('thecode');
    });
  </script>

  <script src="http://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>

마지막으로 :

  <script>for(var f in $d){$d[f]();}</script>
 </body>
<html>

또는 덜 놀라운 버전 :

<script>var def=[];function defer(n){def.push(n)}</script>
<script>
defer(function(){
   $('#thediv').html('thecode');
});
</script>
<script src="http://code.jquery.com/jquery-3.2.1.min.js" type="text/javascript"></script>
<script>for(var f in def){def[f]();}</script>

그리고 비동기의 경우 jquery onload에서 푸시 된 함수를 실행할 수 있습니다.

<script async onload="for(var f in def){def[f]();}" 
src="jquery.min.js" type="text/javascript"></script>

또는 :

function loadscript(src, callback){
  var script = document.createElement('script');
  script.src = src
  script.async = true;
  script.onload = callback;
  document.body.appendChild(script);
};
loadscript("jquery.min", function(){for(var f in def){def[f]();}});

2

그게 당신 문제라고 생각하지 않습니다. 스크립트로드는 기본적으로 동기식이므로 defer속성을 사용하거나 다른 AJAX 요청을 통해 jQuery 자체를로드 하지 않는 한 문제는 404와 비슷할 수 있습니다. 마크 업을 표시하고 의심스러운 내용이 있으면 알려주세요. 방화범이나 웹 관리자?


2

defer()다시 사용할 수 있도록 Dario 에서 확장 해 보겠습니다 .

function defer(toWaitFor, method) {
    if (window[toWaitFor]) {
        method();
    } else {
        setTimeout(function () { defer(toWaitFor, method) }, 50);
    }
}

그런 다음 실행됩니다.

function waitFor() {
    defer('jQuery', () => {console.log('jq done')});
    defer('utag', () => {console.log('utag done')});
}

1

이것을 확인하십시오 :

https://jsfiddle.net/neohunter/ey2pqt5z/

jquery의 onload 메소드를 사용할 수있는 가짜 jQuery 객체를 생성하고 jquery가로드되는 즉시 실행됩니다.

완벽하지 않습니다.

// This have to be on <HEAD> preferibly inline
var delayed_jquery = [];
jQuery = function() {
  if (typeof arguments[0] == "function") {
    jQuery(document).ready(arguments[0]);
  } else {
    return {
      ready: function(fn) {
        console.log("registering function");
        delayed_jquery.push(fn);
      }
    }
  }
};
$ = jQuery;
var waitForLoad = function() {
  if (typeof jQuery.fn != "undefined") {
    console.log("jquery loaded!!!");
    for (k in delayed_jquery) {
      delayed_jquery[k]();
    }
  } else {
    console.log("jquery not loaded..");
    window.setTimeout(waitForLoad, 500);
  }
};
window.setTimeout(waitForLoad, 500);
// end



// now lets use jQuery (the fake version)
jQuery(document).ready(function() {
  alert('Jquery now exists!');
});

jQuery(function() {
  alert('Jquery now exists, this is using an alternative call');
})

// And lets load the real jquery after 3 seconds..
window.setTimeout(function() {
  var newscript = document.createElement('script');
  newscript.type = 'text/javascript';
  newscript.async = true;
  newscript.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js';
  (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(newscript);
}, 3000);


이 문서 준비 기능 덕분에 등록하는 혼전 솔루션입니다
zanedev

0

상의 접선 노트는 여기에 부하 사용에 접근 setTimeout하거나 setInterval. 이 경우 검사가 다시 실행될 때 DOM이 이미로드되고 브라우저의 DOMContentLoaded이벤트가 시작될 수 있으므로 이러한 접근 방식을 사용하여 해당 이벤트를 안정적으로 감지 할 수 없습니다. 내가 찾은 것은 jQuery가 ready여전히 작동 한다는 것이므로 평소와 같이 임베드 할 수 있습니다.

jQuery(document).ready(function ($) { ... }

당신의 내부 setTimeout또는 setInterval모든 것이 정상으로 작동합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.