요소가 존재할 때까지 기다리는 방법?


237

Chrome에서 확장 프로그램을 개발 중이며 요소가 언제 존재하는지 알아내는 가장 좋은 방법은 무엇입니까? 요소가 존재할 때까지 확인하는 간격으로 일반 자바 스크립트를 사용하거나 jQuery가 이것을 수행하는 쉬운 방법이 있습니까?


1
오늘 여기에있는 모든 단일 옵션 (댓글 포함)이 오래되었거나 불완전한 것처럼 보입니다. 그들은 @ hughsk의 멋진 입력을 완벽하게 고려하지 않습니다. 호환성 주장. 한편 Ryan의 대답에 Brandon의 업데이트를 사용하여 일반적인 단순성과 오버 헤드 위험을 줄이는 것이 좋습니다.
cregox

4
MutationObserver> DOM Mutation Events> setTimeout.
mattsven

2
내가 서있는 곳이 아닙니다. setTimeout호환 가능하고 구현이 간단하고 유지 관리가 간단하며 오버 헤드가 거의 없습니다.
cregox

setTimeout+ jQuery는 두 가지 이유로 내 의견으로는 이상적이지 않습니다. 1.) jQuery bloat 2.) 요소에 대해 DOM을 수동으로 불필요하게 쿼리하고 이벤트는 속도면에서 쉽게 이길 수 있습니다 .3) 항상 네이티브보다 느립니다. 이행. 요소의 존재를 기반으로 합리적으로 빠르게 작업해야하는 경우, 특히 원활한 사용자 경험이 목표 인 경우에는 열등합니다.
mattsven

3
세 종류의 사람들이 있습니다 : 셀 수없는 사람들과 셀 수없는 사람들. ; P
cregox

답변:


149

DOMNodeInserted성능 문제로 인해 다른 DOM 돌연변이 이벤트와 함께 더 이상 사용되지 않습니다. 권장되는 방법은 MutationObserver 를 사용 하여 DOM을 보는 것입니다. 최신 브라우저에서만 지원되므로 사용할 수없는 DOMNodeInserted경우 MutationObserver에는 다시 넘어야 합니다.

var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (!mutation.addedNodes) return

    for (var i = 0; i < mutation.addedNodes.length; i++) {
      // do things to your newly added nodes here
      var node = mutation.addedNodes[i]
    }
  })
})

observer.observe(document.body, {
    childList: true
  , subtree: true
  , attributes: false
  , characterData: false
})

// stop watching using:
observer.disconnect()

50
나는 항상 MutationObserver api가 약간 복잡하다는 것을 알았습니다. 따라서 엘리먼트 작성 / 제거를 수신하기 위해 더 간단한 api를 제공하기 위해 arrive.js 라이브러리를 만들었습니다 .
Uzair Farooq

15
@UzairFarooq 우수한 라이브러리 github.com/uzairfarooq/arrive를
Dennis

3
주목해야 할 두 가지 : (1) 빈 배열 인 경우에도 여전히 true를 반환 if (mutation.addedNodes.length)하므로 더 나은 방법 if (mutation.addedNodes)입니다. (2) mutation.addedNodes.forEach()addedNodes가 nodeList이고 forEach를 사용하여 nodeList를 반복 할 수 없으므로 수행 할 수 없습니다. 이에 대한 해결책은 toddmotto.com/ditch-the-array-foreach-call-nodelist-hack
thdoan

3
이것을 어떻게 사용하는지 예를 들어 줄 수 있습니까? DOM 요소가 존재할 때 실행하려는 jquery 선택기 또는 코드를 어디에 둘지 확실하지 않습니다.
Superdooperhero 13:30에

1
@Superdooperhero 나는 쉬운 예를 들어 대답했다. 확인해 봐. stackoverflow.com/a/57395241/6542186
SilverSurfer

113

나는이 같은 문제를 겪고 있었기 때문에 플러그인 을 작성했다.

$(selector).waitUntilExists(function);

암호:

;(function ($, window) {

var intervals = {};
var removeListener = function(selector) {

    if (intervals[selector]) {

        window.clearInterval(intervals[selector]);
        intervals[selector] = null;
    }
};
var found = 'waitUntilExists.found';

/**
 * @function
 * @property {object} jQuery plugin which runs handler function once specified
 *           element is inserted into the DOM
 * @param {function|string} handler 
 *            A function to execute at the time when the element is inserted or 
 *            string "remove" to remove the listener from the given selector
 * @param {bool} shouldRunHandlerOnce 
 *            Optional: if true, handler is unbound after its first invocation
 * @example jQuery(selector).waitUntilExists(function);
 */

$.fn.waitUntilExists = function(handler, shouldRunHandlerOnce, isChild) {

    var selector = this.selector;
    var $this = $(selector);
    var $elements = $this.not(function() { return $(this).data(found); });

    if (handler === 'remove') {

        // Hijack and remove interval immediately if the code requests
        removeListener(selector);
    }
    else {

        // Run the handler on all found elements and mark as found
        $elements.each(handler).data(found, true);

        if (shouldRunHandlerOnce && $this.length) {

            // Element was found, implying the handler already ran for all 
            // matched elements
            removeListener(selector);
        }
        else if (!isChild) {

            // If this is a recurring search or if the target has not yet been 
            // found, create an interval to continue searching for the target
            intervals[selector] = window.setInterval(function () {

                $this.waitUntilExists(handler, shouldRunHandlerOnce, true);
            }, 500);
        }
    }

    return $this;
};

}(jQuery, window));

5
플러그인 주셔서 감사합니다. 나는 포크로 조금 개선했다. 내 업데이트에서 원하는 것을 자유롭게 가져 가십시오. 나는 여전히 몇 가지 개선 계획을 세웠습니다 : 플러그인 업데이트
Brandon Belvin

8
jquery dep 없이도 좋을 것입니다 ...;)
knutole

4
어쩌면 당신은 그것이 어떻게 작동하는지 언급해야 할 것입니다 : 요소가 존재하는지 (a를 사용하여 window.setInterval) 500 ms마다 묻는다 . MutationObserver설문 조사를 통해 답변 이 제대로 작동 하는지 모르겠습니다 ...
sports

2
요소가 이미 페이지에 있으면 제대로 작동하지 않습니다. 여기에서이 함수의 적절한 버전이다 gist.github.com/PizzaBrandon/5709010
롤랜드 Soós

2
;함수 시작 부분에서 무엇을 사용하는지 설명해 주 ;(function ($, window) {시겠습니까?
mrid dec

76

다음은 요소 표시를 기다리는 핵심 JavaScript 함수입니다.

매개 변수 :

  1. selector:이 함수는 $ {selector} 요소를 찾습니다.
  2. time:이 함수는이 요소가 $ {time} 밀리 초마다 존재하는지 확인합니다.

    function waitForElementToDisplay(selector, time) {
            if(document.querySelector(selector)!=null) {
                alert("The element is displayed, you can put your code instead of this alert.")
                return;
            }
            else {
                setTimeout(function() {
                    waitForElementToDisplay(selector, time);
                }, time);
            }
        }

예를 들어, 설정 selector="#div1"time=5000그 HTML 태그를 찾습니다 id="div1"마다 5000 밀리 초.


좋은! 어떤 셀렉터라도 받아 들일 수 있도록 이것을 쓸 수 있습니까?
mattsven

나는 그것을 할 수 없다고 생각한다. 그러나 getElementByXpath를 얻기 위해이 포스트를 봐라 : stackoverflow.com/questions/10596417/…
Etienne Tonnelier


1
대신 돌연변이 관찰자를 사용하도록 작성할 수 있습니까?
SuperUberDuper 2016 년

아니면 약속을 사용하기 위해 이것을 다시 쓸 수 있습니까?
SuperUberDuper 2016 년

25

DOM에 새 요소가 추가 될 때마다 발생하는 이벤트를 청취 DOMNodeInserted하거나 들을 수 있습니다 DOMSubtreeModified.

새 요소가 생성되는시기를 감지하는 LiveQuery jQuery 플러그인 도 있습니다 .

$("#future_element").livequery(function(){
    //element created
});

1
아주 좋은 플러그인! jquery에 직접 그러한 기능이 있습니까? 기존 기능이 없는지 궁금합니다. 그리고 이것이 플러그인이라면이 답변에 투표하십시오.) 나에게는 완벽하게 작동합니다. 대단히 감사합니다.
사무엘

1
참고 IE 9는 DOMNodeInserted를 구현하지만 대부분의 시간 동안 요소를 추가 할 때 발생하지 않는 주요 버그가 있습니다. : 세부 사항에 있습니다 help.dottoro.com/ljmcxjla.php
mikemaccana

23

이 접근법을 사용하여 요소가 나타날 때까지 기다렸다가 그 후에 다른 기능을 실행할 수 있습니다.

doTheRestOfTheStuff(parameters)ID the_Element_ID가 있는 요소가 나타나거나로드가 완료된 후에 만 함수를 호출해야 한다고 가정 해 보겠습니다 .

var existCondition = setInterval(function() {
 if ($('#the_Element_ID').length) {
    console.log("Exists!");
    clearInterval(existCondition);
    doTheRestOfTheStuff(parameters);
 }
}, 100); // check every 100ms

21

넌 할 수있어

$('#yourelement').ready(function() {

});

이것은 서버에서 요청할 때 요소가 DOM에 존재하는 경우에만 작동합니다. 요소가 JavaScript를 통해 동적으로 추가되는 경우 작동하지 않으며 다른 답변을 봐야 할 수도 있습니다.


7
.ready()함수는뿐만 아니라 대부분의 항목 (아무것도 아닌 경우)에서 작동합니다 document. 에서조차 동적으로 생성 된 요소에서는 작동하지 않습니다 .live().
Richard Neil Ilagan

7
@Bery는 Richard가 지적했듯이 HTML이 서버에서 처음 요청할 때 이미 존재하는 요소에 대해서만 작동합니다. Javascript를 사용하여 DOM에 요소를 동적으로 추가하면 작동하지 않습니다.
Chandranshu

6
@ Sam, 메모리의 요소 참조에 첨부하는 방법을 분명히 설명해 주시겠습니까?
Vikas Singhal

3
이 답변은 잘못되었습니다. 실제로 여기서 확인하고있는 것은 규칙적 $(document).ready()이며 적용 할 요소는 아닙니다. 이것이 바로이 특별한 청취자가 작동하는 방식입니다.
Shikkediel

1
이 사용은 따라하지 않는 것이 좋습니다 api.jquery.com/ready
splintor

14

나는 여전히 쉽고 읽기 쉬운 작업 예제와 함께 여기에 어떤 대답도 없다고 생각합니다. MutationObserver interface 를 사용 하여 다음과 같이 DOM 변경을 감지하십시오.

var observer = new MutationObserver(function(mutations) {
    if ($("p").length) {
        console.log("Exist, lets do something");
        observer.disconnect(); 
        //We can disconnect observer once the element exist if we dont want observe more changes in the DOM
    }
});

// Start observing
observer.observe(document.body, { //document.body is node target to observe
    childList: true, //This is a must have for the observer with subtree
    subtree: true //Set to true if changes must also be observed in descendants.
});
            
$(document).ready(function() {
    $("button").on("click", function() {
        $("p").remove();
        setTimeout(function() {
            $("#newContent").append("<p>New element</p>");
        }, 2000);
    });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<button>New content</button>
<div id="newContent"></div>

참고 : 자세한 정보를 원하면 스페인어 Mozilla 문서 MutationObserver가 더 자세합니다.


2
downvote의 이유를 설명하는 의견을 남겨 주시면 답변을 개선 할 수 있습니다. 감사.
SilverSurfer

12

원하는 선택기를 추가하기 만하면됩니다. 요소가 발견되면 콜백 함수에서 액세스 할 수 있습니다.

const waitUntilElementExists = (selector, callback) => {
const el = document.querySelector(selector);

if (el){
    return callback(el);
}

setTimeout(() => waitUntilElementExists(selector, callback), 500);
}

waitUntilElementExists('.wait-for-me', (el) => console.log(el));

2
동의안에, 이것은 매우 깨끗한 해결책이며 나를 위해 일합니다.
jstafford

3
이 답변은 최신 브라우저뿐만 아니라 IE8-10에서도 작동합니다. 가장 큰 문제는 요소가 존재하지 않으면 계속 실행된다는 것입니다. 따라서 요소가있을 때 가장 좋은 시점입니다. 그렇지 않으면 카운터를 추가 할 수 있습니다.
이름을 위해

1
나를 위해 완벽하게 일
제임스 스튜어트

1
매력처럼 일했습니다!
Aman

1
그것들은 비슷하고 동일하지 않았습니다. 또한 많은 사람들이 같은 일을하고 있습니다. 마지막 으로이 솔루션을 직접 코딩했습니다. 그것은 나쁜 추론이지만, 사실이라도 사실이라면 알려주는 의견에 감사드립니다. 그 대답은 OP의 문제를 해결하고 명백한 동기가 없습니다.
Diego Fortes

11

jQuery를 사용하는 간단한 접근법을 위해 이것이 잘 작동한다는 것을 알았습니다.

  // Wait for element to exist.
  function elementLoaded(el, cb) {
    if ($(el).length) {
      // Element is now loaded.
      cb($(el));
    } else {
      // Repeat every 500ms.
      setTimeout(function() {
        elementLoaded(el, cb)
      }, 500);
    }
  };

  elementLoaded('.element-selector', function(el) {
    // Element is ready to use.
    el.click(function() {
      alert("You just clicked a dynamically inserted element");
    });
  });

여기서 우리는 단순히 500ms마다 요소가로드되었는지 여부를 확인하기 위해 검사합니다.

이는 문서에 동적으로 추가 된 요소에 클릭 핸들러를 추가 할 때 특히 유용합니다.


8

방법에 대한 insertionQuery의 도서관은?

insertionQuery는 지정된 선택기에 첨부 된 CSS 애니메이션 콜백을 사용하여 요소가 작성 될 때 콜백을 실행합니다. 이 메소드를 사용하면 처음이 아닌 요소를 만들 때마다 콜백을 실행할 수 있습니다.

github에서 :

나타나는 노드를 잡는 비 이벤트 방식. 그리고 선택기를 사용합니다.

광범위한 브라우저 지원뿐만 아니라 DOMMutationObserver보다 낫습니다.

왜?

  • DOM 이벤트로 인해 브라우저 속도가 느려지고 insertionQuery가
  • DOM Mutation Observer는 insertionQuery보다 브라우저 지원이 적기 때문에
  • insertionQuery를 사용하면 성능 오버 헤드없이 선택기를 사용하여 DOM 변경을 필터링 할 수 있습니다!

폭 넓은 지원!

IE10 + 및 대부분 기타 (모바일 포함)


7

다음은 MutationObserver의 얇은 래퍼 역할을하는 함수입니다. 브라우저가 MutationObserver를 지원해야합니다. JQuery에 의존하지 않습니다. 실제 예제를 보려면 아래 스 니펫을 실행하십시오.

function waitForMutation(parentNode, isMatchFunc, handlerFunc, observeSubtree, disconnectAfterMatch) {
  var defaultIfUndefined = function(val, defaultVal) {
    return (typeof val === "undefined") ? defaultVal : val;
  };

  observeSubtree = defaultIfUndefined(observeSubtree, false);
  disconnectAfterMatch = defaultIfUndefined(disconnectAfterMatch, false);

  var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
      if (mutation.addedNodes) {
        for (var i = 0; i < mutation.addedNodes.length; i++) {
          var node = mutation.addedNodes[i];
          if (isMatchFunc(node)) {
            handlerFunc(node);
            if (disconnectAfterMatch) observer.disconnect();
          };
        }
      }
    });
  });

  observer.observe(parentNode, {
    childList: true,
    attributes: false,
    characterData: false,
    subtree: observeSubtree
  });
}

// Example
waitForMutation(
  // parentNode: Root node to observe. If the mutation you're looking for
  // might not occur directly below parentNode, pass 'true' to the
  // observeSubtree parameter.
  document.getElementById("outerContent"),
  // isMatchFunc: Function to identify a match. If it returns true,
  // handlerFunc will run.
  // MutationObserver only fires once per mutation, not once for every node
  // inside the mutation. If the element we're looking for is a child of
  // the newly-added element, we need to use something like
  // node.querySelector() to find it.
  function(node) {
    return node.querySelector(".foo") !== null;
  },
  // handlerFunc: Handler.
  function(node) {
    var elem = document.createElement("div");
    elem.appendChild(document.createTextNode("Added node (" + node.innerText + ")"));
    document.getElementById("log").appendChild(elem);
  },
  // observeSubtree
  true,
  // disconnectAfterMatch: If this is true the hanlerFunc will only run on
  // the first time that isMatchFunc returns true. If it's false, the handler
  // will continue to fire on matches.
  false);

// Set up UI. Using JQuery here for convenience.

$outerContent = $("#outerContent");
$innerContent = $("#innerContent");

$("#addOuter").on("click", function() {
  var newNode = $("<div><span class='foo'>Outer</span></div>");
  $outerContent.append(newNode);
});
$("#addInner").on("click", function() {
  var newNode = $("<div><span class='foo'>Inner</span></div>");
  $innerContent.append(newNode);
});
.content {
  padding: 1em;
  border: solid 1px black;
  overflow-y: auto;
}
#innerContent {
  height: 100px;
}
#outerContent {
  height: 200px;
}
#log {
  font-family: Courier;
  font-size: 10pt;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Create some mutations</h2>
<div id="main">
  <button id="addOuter">Add outer node</button>
  <button id="addInner">Add inner node</button>
  <div class="content" id="outerContent">
    <div class="content" id="innerContent"></div>
  </div>
</div>
<h2>Log</h2>
<div id="log"></div>


6

다음은 바닐라 자바 ​​스크립트의 약속 반환 솔루션입니다 (지저분한 콜백 없음). 기본적으로 200ms마다 확인합니다.

function waitFor(selector) {
    return new Promise(function (res, rej) {
        waitForElementToDisplay(selector, 200);
        function waitForElementToDisplay(selector, time) {
            if (document.querySelector(selector) != null) {
                res(document.querySelector(selector));
            }
            else {
                setTimeout(function () {
                    waitForElementToDisplay(selector, time);
                }, time);
            }
        }
    });
}

5

다음은 모든 것을 기다릴 수있는 순수한 자바 스크립트 함수입니다. CPU 리소스를 덜 사용하려면 간격을 길게 설정하십시오.

/**
 * @brief Wait for something to be ready before triggering a timeout
 * @param {callback} isready Function which returns true when the thing we're waiting for has happened
 * @param {callback} success Function to call when the thing is ready
 * @param {callback} error Function to call if we time out before the event becomes ready
 * @param {int} count Number of times to retry the timeout (default 300 or 6s)
 * @param {int} interval Number of milliseconds to wait between attempts (default 20ms)
 */
function waitUntil(isready, success, error, count, interval){
    if (count === undefined) {
        count = 300;
    }
    if (interval === undefined) {
        interval = 20;
    }
    if (isready()) {
        success();
        return;
    }
    // The call back isn't ready. We need to wait for it
    setTimeout(function(){
        if (!count) {
            // We have run out of retries
            if (error !== undefined) {
                error();
            }
        } else {
            // Try again
            waitUntil(isready, success, error, count -1, interval);
        }
    }, interval);
}

예를 들어 jQuery에서 이것을 호출하려면 다음과 같이 사용하십시오.

waitUntil(function(){
    return $('#myelement').length > 0;
}, function(){
    alert("myelement now exists");
}, function(){
    alert("I'm bored. I give up.");
});

3

a를 반환하고 Promise시간 초과를 사용할 수 있는 솔루션 (IE 11 이상 호환).

단일 요소 (요소 유형)의 경우 :

"use strict";

function waitUntilElementLoaded(selector) {
    var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

    var start = performance.now();
    var now = 0;

    return new Promise(function (resolve, reject) {
        var interval = setInterval(function () {
            var element = document.querySelector(selector);

            if (element instanceof Element) {
                clearInterval(interval);

                resolve();
            }

            now = performance.now();

            if (now - start >= timeout) {
                reject("Could not find the element " + selector + " within " + timeout + " ms");
            }
        }, 100);
    });
}

여러 요소 (NodeList 유형)의 경우 :

"use strict";

function waitUntilElementsLoaded(selector) {
    var timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

    var start = performance.now();
    var now = 0;

    return new Promise(function (resolve, reject) {
        var interval = setInterval(function () {
            var elements = document.querySelectorAll(selector);

            if (elements instanceof NodeList) {
                clearInterval(interval);

                resolve(elements);
            }

            now = performance.now();

            if (now - start >= timeout) {
                reject("Could not find elements " + selector + " within " + timeout + " ms");
            }
        }, 100);
    });
}

예 :

waitUntilElementLoaded('#message', 800).then(function(element) {
    // element found and available

    element.innerHTML = '...';
}).catch(function() {
    // element not found within 800 milliseconds
});

waitUntilElementsLoaded('.message', 10000).then(function(elements) {
    for(const element of elements) {
        // ....
    }
}).catch(function(error) {
    // elements not found withing 10 seconds
});

요소 목록과 단일 요소 모두에서 작동합니다.


1
내가 가장 좋아하는 솔루션! 왜 확인 element instanceof HTMLElement합니까? null또는 이외의 다른 것이 될 수 있습니까 HTMLElement?
Leeroy

1
당신은 흥미로운 지적을합니다. Element대신 (고정) 을 사용하여 더 넓게 만들어야했습니다 . Element MDN 문서에 나와있는 것처럼 변수 element에 속성이 있는지 확인하고 싶기 때문에 확인합니다 . 신경 쓰지 않으면 제거하십시오! innerHTML
Anwar

2

MutationObserver를 사용하는 깔끔한 예 :

new MutationObserver( mutation => {
    if (!mutation.addedNodes) return
    mutation.addedNodes.forEach( node => {
        // do stuff with node
    })
})

2

이것은 약속에 익숙하고 타사 라이브러리 또는 타이머를 사용하고 싶지 않은 사람들을위한 간단한 솔루션입니다.

나는 내 프로젝트에서 잠시 동안 그것을 사용 해왔다

function waitForElm(selector) {
    return new Promise(resolve => {
        if (document.querySelector(selector)) {
            return resolve(document.querySelector(selector));
        }

        const observer = new MutationObserver(mutations => {
            if (document.querySelector(selector)) {
                resolve(document.querySelector(selector));
                observer.disconnect();
            }
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    });
}

그것을 사용하려면 :

waitForElm('.some-class').then(elm => console.log(elm.textContent));

또는 async / await

const elm = await waitForElm('.some-classs')

깔끔하다! 멋진 부분은 async/ 와 함께 사용할 수 있다는 것 await입니다. 다음을 수행하여 성능을 더 향상시킬 수도 있습니다.mutations.addedNodes.find(node => node.matchesSelector("..."))
mattsven

@mattsven 좋은 지적입니다! 돌연변이의 노드 만 확인하는 것이 document.querySelector를 수행하는 것보다 성능이 좋습니다.
Yong Wang

맞춤법 실수 watiForElm을 waitForElm
dalvir로 수정하십시오.

1

잠시 후 (시간 초과)를 보지 않으려면 다음 jQuery가 작동합니다. 10 초 후에 시간이 초과됩니다. 이름을 통해 입력을 선택해야하고 다른 솔루션 중 일부를 구현하는 데 어려움이 있기 때문에 순수 JS 대신이 코드를 사용해야했습니다.

 // Wait for element to exist.

    function imageLoaded(el, cb,time) {

        if ($(el).length) {
            // Element is now loaded.

            cb($(el));

            var imageInput =  $('input[name=product\\[image_location\\]]');
            console.log(imageInput);

        } else if(time < 10000) {
            // Repeat every 500ms.
            setTimeout(function() {
               time = time+500;

                imageLoaded(el, cb, time)
            }, 500);
        }
    };

    var time = 500;

    imageLoaded('input[name=product\\[image_location\\]]', function(el) {

     //do stuff here 

     },time);

0

저는 보통 태그 관리자에이 스 니펫을 사용합니다.

<script>
(function exists() {
  if (!document.querySelector('<selector>')) {
    return setTimeout(exists);
  }
  // code when element exists
})();  
</script>

0

비동기 dom 변경이있는 경우이 함수는 DOM 요소를 확인 (시간 제한)하여 DOM 및 Promise 기반 :)에 무겁지 않습니다.

function getElement(selector, i = 5) {
  return new Promise(async (resolve, reject) => {
    if(i <= 0) return reject(`${selector} not found`);
    const elements = document.querySelectorAll(selector);
    if(elements.length) return resolve(elements);
    return setTimeout(async () => await getElement(selector, i-1), 1000);
  })
}

// Now call it with your selector

try {
  element = await getElement('.woohoo');
} catch(e) { // catch the e }

//OR

getElement('.woohoo', 5)
.then(element => { // do somthing with the elements })
.catch(e => { // catch the error });
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.