किसी तत्व के मौजूद होने तक इंतजार कैसे करें?


236

मैं क्रोम में एक एक्सटेंशन पर काम कर रहा हूं, और मैं सोच रहा हूं: किसी तत्व के अस्तित्व में आने का सबसे अच्छा तरीका क्या है? सादे जावास्क्रिप्ट का उपयोग करना, एक अंतराल के साथ जो एक तत्व मौजूद होने तक जांच करता है, या jQuery के पास ऐसा करने का कोई आसान तरीका है?


1
आज यहां हर एक विकल्प दिखता है (टिप्पणियों से सहित) या तो पुराना या अधूरा है। वे पूरी तरह से @ ह्यूगस्क के भयानक इनपुट पर विचार नहीं करते हैं, संगतता तर्क। इस बीच, मैं साधारण सादगी और ओवरहेड के कम जोखिम के लिए रेयान के जवाब पर ब्रैंडन के अपडेट का उपयोग करने की सलाह देता हूं, मुझे लगता है।
cregox

4
MutationObserver> DOM Mutation Events> setTimeout
mattsven

2
मैं जहां खड़ा हूं वहां से नहीं। setTimeoutसंगत है, लागू करने के लिए सरल है, बनाए रखने के लिए सरल है, और नगण्य ओवरहेड है।
cregox

setTimeout+ jQueryदो कारणों से मेरी राय में आदर्श से कम है: 1.) jQuery के bloat 2.) आप अनावश्यक रूप से तत्वों के लिए DOM को क्वेरी कर रहे हैं, घटनाओं ने उस गति-वार को आसानी से हरा दिया, 3.) यह हमेशा किसी भी मूल की तुलना में धीमा होगा कार्यान्वयन। यदि आपको किसी तत्व की मौजूदगी के आधार पर कुछ भी करने की आवश्यकता है तो जल्दी से, खासकर यदि निर्बाध उपयोगकर्ता अनुभव आपका लक्ष्य है, तो यह हीन है।
Mattsven

3
लोगों के 3 प्रकार हैं: वे जो गिन सकते हैं और जो नहीं कर सकते हैं। ; पी
cregox

जवाबों:


148

DOMNodeInsertedप्रदर्शन मुद्दों के कारण, अन्य DOM उत्परिवर्तन घटनाओं के साथ, पदावनत किया जा रहा है - अनुशंसित दृष्टिकोण DOM देखने के लिए MutationObserver का उपयोग करना है । यह केवल नए ब्राउज़रों में ही समर्थित है, इसलिए 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 एपीआई को थोड़ा जटिल पाया है इसलिए मैंने तत्वों के निर्माण / हटाने के लिए सुनने के लिए एक सरल एपीआई प्रदान करने के लिए एक पुस्तकालय, आगमन.जेएस का निर्माण किया है।
उज़ैर फ़ारूक़

15
मैं @UairairFarooq उत्कृष्ट पुस्तकालय का उपयोग करने की सलाह देता हूं github.com/uzairfarooq/arrive
डेनिस

3
टिप्पणी करने के लिए दो बातें: (1) यह करने के लिए बेहतर होगा if (mutation.addedNodes.length), क्योंकि if (mutation.addedNodes)अभी भी सच वापसी होगी भले ही वह एक खाली सरणी है। (2) आप ऐसा नहीं कर सकते mutation.addedNodes.forEach()क्योंकि AddNodes एक नोडलिस्ट है और आप फॉरएच के साथ नोडलिस्ट के माध्यम से पुनरावृति नहीं कर सकते। इसके समाधान के लिए, toddmotto.com/ditch-the-array-foreach-call-nodelist-hack
4

3
क्या आप इस बात का उदाहरण दे सकते हैं कि कोई इसका उपयोग कैसे करेगा? सुनिश्चित नहीं है कि मेरे jquery चयनकर्ता या कोड को कहां रखा जाए जो मैं चाहता हूं कि DOM तत्व मौजूद है।
सुपरडोपरेरो

1
@Superdooperhero मैंने आसान उदाहरण के साथ एक उत्तर दिया। इसे जाँचे। stackoverflow.com/a/57395241/6542186
सिल्वरसर्फर

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
प्लगइन के लिए धन्यवाद। मैंने कांटा लगाया और इसमें थोड़ा सुधार किया। मेरे अपडेट से जो भी आप चाहते हैं उसे लेने के लिए स्वतंत्र महसूस करें। मेरे पास कुछ और सुधार की योजना है, फिर भी: अपडेट किया गया प्लगइन
ब्रैंडन बेल्विन

8
); भी jQuery डीईपी बिना अच्छा होगा ...
knutole

4
शायद आपको यह उल्लेख करना चाहिए कि यह कैसे काम करता है: यह प्रत्येक 500 एमएस से पूछकर काम करता है यदि तत्व मौजूद है (ए window.setInterval) का उपयोग कर रहा है । मुझे नहीं पता कि क्या MutationObserverजवाब मतदान के रूप में अच्छी तरह से काम करता है ...
खेल

2
यदि तत्व पहले से ही पृष्ठ पर है, तो यह ठीक से काम नहीं करता है। यहाँ इस समारोह का उचित संस्करण है: gist.github.com/PizzaBrandon/5709010
रोलैंड सूस

2
क्या आप कृपया बता सकते हैं ;कि फ़ंक्शन की शुरुआत में ( ;(function ($, window) {) का उपयोग क्या है ?
मृग

76

एक तत्व के प्रदर्शन की प्रतीक्षा करने के लिए यहां एक कोर जावास्क्रिप्ट फ़ंक्शन है।

पैरामीटर:

  1. selector: यह फ़ंक्शन तत्व $ {चयनकर्ता} के लिए दिखता है
  2. 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=5000HTML टैग की तलाश करेगा जिसका id="div1"प्रत्येक 5000 मिलीसेकंड है।


अच्छा! क्या आप इसे लिख सकते हैं ताकि किसी भी चयनकर्ता को स्वीकार किया जा सके?
Mattsven

मुझे शक है कि मैं यह कर सकता हूँ .. लेकिन कृपया इस पोस्ट पर एक नज़र पाने के लिए GetElementByXpath: stackoverflow.com/questions/10596417/…
Etienne Tonnelier

1
किस बारे में querySelector? developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
mattsven

1
क्या आप इसके बदले म्यूटेशन ऑब्जर्वर का उपयोग करने के लिए लिख सकते हैं?
सुपरयूपरड्यूपर

या क्या आप वादे का उपयोग करने के लिए इसे फिर से लिख सकते हैं?
SuperUberDuper

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)आईडी के 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 में मौजूद हो। यदि तत्व को जावास्क्रिप्ट के माध्यम से गतिशील रूप से जोड़ा जा रहा है, तो यह काम नहीं करेगा और आपको अन्य उत्तरों को देखने की आवश्यकता हो सकती है।


7
.ready()सबसे कुछ भी समारोह काम करता है (अगर कुछ भी नहीं), बस नहीं document। यह सिर्फ गतिशील रूप से बनाए गए तत्वों के साथ भी काम नहीं करेगा .live()
रिचर्ड नील इलगन

7
@Bery, जैसा कि रिचर्ड ने बताया, यह केवल उन तत्वों के लिए काम करता है जो पहले से ही HTML में मौजूद होते हैं जब यह सर्वर से पहली बार अनुरोध किया जाता है। यदि जावास्क्रिप्ट का उपयोग DOM में किसी तत्व को गतिशील रूप से जोड़ने के लिए किया जाता है, तो यह काम नहीं करता है।
चंद्रवंशी

6
@ मेम, क्या आप स्पष्ट कर सकते हैं कि इसे स्मृति में तत्व के संदर्भ में कैसे संलग्न किया जाए?
विकास सिंघल

3
यह उत्तर गलत है। जो आप वास्तव में यहां देख रहे हैं वह एक नियमित है $(document).ready(), न कि वह तत्व जो आपको लगता है कि यह भी लागू होगा। बस यही खास श्रोता काम करता है। उदाहरण
शिक्केडियल

1
यह प्रयोग api.jquery.com/ready
splintor

14

मुझे लगता है कि अभी भी आसान और पठनीय कार्य उदाहरण के साथ यहाँ कोई जवाब नहीं है। DOM परिवर्तनों का पता लगाने के लिए MutationObserver interface का उपयोग करें , जैसे:

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>

नोट: यदि आप अधिक जानकारी चाहते हैं तो स्पेनिश मोज़िला डॉक्स MutationObserverअधिक विस्तृत हैं।


2
डाउनवोट के कारण को स्पष्ट करने वाली टिप्पणी पर विचार करें, इसलिए मैं अपने उत्तर में सुधार कर सकता हूं। धन्यवाद।
सिल्वरसर्फर

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
आकर्षण की तरह काम किया !!
अमन

1
वे समान थे, समान नहीं थे। इसके अलावा, कई लोग ऐसा ही कर रहे हैं। अंत में, मैंने इस समाधान को स्वयं कोडित किया। हालांकि, यह एक खराब तर्क है, अगर यह वास्तव में मामला था, तो मैं एक टिप्पणी की सराहना करूंगा, जो मुझे बताएगी। उत्तर ओपी के मुद्दे को हल करता है और इसका कोई स्पष्ट मकसद नहीं है।
डिएगो फोर्ट्स

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

सम्मिलन पुस्तकालय के बारे में कैसे ?

सम्मिलन एक तत्व निर्मित होने पर कॉलबैक चलाने के लिए निर्दिष्ट चयनकर्ता (एस) से जुड़ी सीएसएस एनीमेशन कॉलबैक का उपयोग करता है। यह विधि कॉलबैक को तब चलाने की अनुमति देती है जब कोई तत्व बनाया जाता है, न कि पहली बार।

जीथब से:

दिखाने के लिए नोड्स को पकड़ने के लिए गैर-डोम-ईवेंट तरीका। और यह चयनकर्ताओं का उपयोग करता है।

यह केवल व्यापक ब्राउज़र समर्थन के लिए नहीं है, यह कुछ चीजों के लिए DOMMutationObserver से बेहतर हो सकता है।

क्यों?

  • क्योंकि DOM ईवेंट ब्राउज़र को धीमा कर देता है और सम्मिलन नहीं करता है
  • क्योंकि DOM Mutation Observer में सम्मिलन की तुलना में कम ब्राउज़र सपोर्ट है
  • क्योंकि सम्मिलन के साथ आप प्रदर्शन ओवरहेड के बिना चयनकर्ताओं का उपयोग करके डोम परिवर्तन को फ़िल्टर कर सकते हैं!

व्यापक समर्थन!

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

एक समाधान एक वापसी 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);
    });
}

कई तत्वों के लिए (टाइप करें नोडलिस्ट):

"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?
लेरॉय

1
आप एक दिलचस्प बात उठाते हैं। मुझे Elementइसके बजाय (निश्चित) का उपयोग करके इसे व्यापक बनाना चाहिए । मैं सिर्फ चेक बनाता हूं क्योंकि मैं यह सुनिश्चित करना चाहता हूं कि चर के elementपास तत्व एमडीएन प्रलेखन राज्यों केinnerHTML रूप में संपत्ति है । यदि आप इसकी परवाह नहीं करते हैं तो इसे हटाने के लिए स्वतंत्र महसूस करें!
अनवर

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 / प्रतीक्षा के साथ

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

यह साफ है! इसके बारे में अच्छा हिस्सा यह है कि आप इसे async/ के साथ awaitभी इस्तेमाल कर सकते हैं । हो सकता है कि आप इसे और अधिक प्रदर्शन करने में सक्षम होंmutations.addedNodes.find(node => node.matchesSelector("..."))
मैट्सवेन

@mattsven अच्छा बिंदु! म्यूटेशन में सिर्फ नोड्स की जाँच करना document.querySelector की तुलना में अधिक परफॉर्मेंट है।
योंग वांग

कृपया वर्तनी की गलती सुधारें, watiForElm to WaitForElm
dalvir

1

यदि आप चाहते हैं कि यह थोड़ी देर (टाइमआउट) के बाद दिखना बंद हो जाए तो निम्नलिखित jQuery काम करेगा। यह 10sec के बाद का समय होगा। मुझे शुद्ध जेएस के बजाय इस कोड का उपयोग करने की आवश्यकता थी क्योंकि मुझे नाम के माध्यम से एक इनपुट का चयन करने की आवश्यकता थी और कुछ अन्य समाधानों को लागू करने में परेशानी हो रही थी।

 // 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

यदि आपके पास async डोम परिवर्तन हैं, तो यह फ़ंक्शन DOM तत्वों के लिए (सेकंड में समय सीमा के साथ) चेक करता है, यह DOM और इसके प्रॉमिस बेस्ड के लिए भारी नहीं होगा :)

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 });
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.