কোনও উপাদান উপস্থিত না হওয়া পর্যন্ত কীভাবে অপেক্ষা করবেন?


236

আমি ক্রোমে একটি এক্সটেনশনে কাজ করছি, এবং আমি ভাবছি: কোনও উপাদান কখন অস্তিত্বশীল হয় তা আবিষ্কার করার সর্বোত্তম উপায় কোনটি? সরল জাভাস্ক্রিপ্ট ব্যবহার করে, এমন বিরতি দিয়ে যা কোনও উপাদান উপস্থিত না হওয়া পর্যন্ত পরীক্ষা করে, বা jQuery এর এটি করার কোনও সহজ উপায় আছে?


1
মনে হচ্ছে আজ এখানে প্রতিটি একক বিকল্প (মন্তব্যগুলি সহ) হয় পুরানো বা অসম্পূর্ণ। তারা @ হুগস্কের অসাধারণ ইনপুটটিকে সম্পূর্ণভাবে সামঞ্জস্য করার যুক্তি বিবেচনা করে না। আমি মনে করি, সাধারণ সরলতার জন্য এবং ওভারহেডের কম ঝুঁকির জন্য আমি রায়ের উত্তর সম্পর্কে ব্র্যান্ডনের আপডেটটি কেবলমাত্র ব্যবহার করার পরামর্শ দিই I
ক্রেগোক্স

4
MutationObserver> DOM Mutation Events> setTimeout
ম্যাটসভেন

2
আমি যেখান থেকে দাঁড়িয়েছি তা নয়। setTimeoutসামঞ্জস্যপূর্ণ, প্রয়োগ করা সহজ, বজায় রাখা সহজ, এবং ওভারহেডের উপেক্ষিত।
ক্রেগোক্স

setTimeout+ jQueryদুটি কারণে আমার মতে আদর্শের চেয়ে কম: 1.) jQuery ফোলা 2) আপনি অকারণে ম্যানুয়ালি উপাদানগুলির জন্য ডিওএম অনুসন্ধান করছেন, ঘটনাগুলি দ্রুতগতির সাথে সহজেই পরাজিত হয়, ৩.) এটি সর্বদা যে কোনও নেটিভের চেয়ে ধীর হবে will বাস্তবায়ন. যুক্তিযুক্তভাবে দ্রুত কোনও উপাদানের উপস্থিতির উপর ভিত্তি করে আপনার যদি কিছু করার দরকার হয়, বিশেষত যদি নির্বিঘ্ন ব্যবহারকারীর অভিজ্ঞতা আপনার লক্ষ্য হয় তবে তা নিকৃষ্ট হয়।
ম্যাটসভেন

3
এখানে 3 ধরণের লোক রয়েছে: যারা গণনা করতে পারেন এবং যারা পারেন না তারা। ; পি
ক্রেগোক্স

উত্তর:


148

DOMNodeInsertedপারফরম্যান্স সমস্যার কারণে অন্যান্য ডিওএম মিউটেশন ইভেন্টগুলি সহ অবহিত করা হচ্ছে - প্রস্তাবিত পদ্ধতিটি হ'ল ডিওএম দেখার জন্য মিউটেশনঅবার্সার ব্যবহার করা। এটি কেবলমাত্র নতুন ব্রাউজারগুলিতে সমর্থিত, সুতরাং 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
আমি সর্বদা মিউটেশনঅবার্সার এপিটিকে কিছুটা জটিল খুঁজে পেয়েছি তাই উপাদান তৈরি / অপসারণের জন্য শোনার জন্য একটি সহজ এপিআই সরবরাহ করার জন্য আমি একটি লাইব্রেরি তৈরি করেছি, पहुंच.js
উজাইর ফারুক

15
আমি @ উজাইরফারুউক দুর্দান্ত লাইব্রেরি github.com/uzairfarooq/arrive
ডেনিস

3
দুটি বিষয় লক্ষণীয়: (1) এটি করা ভাল if (mutation.addedNodes.length)কারণ যেহেতু if (mutation.addedNodes)এটি খালি অ্যারে হলেও সত্য ফিরে আসবে। (২) আপনি করতে পারবেন না mutation.addedNodes.forEach()কারণ যুক্ত নোডগুলি নোডলিস্ট এবং আপনি ফোর ইচ সহ নোডলিস্টের মাধ্যমে পুনরাবৃত্তি করতে পারবেন না। এই একটি সমাধান জন্য, দেখুন toddmotto.com/ditch-the-array-foreach-call-nodelist-hack
thdoan

3
কেউ কীভাবে এটি ব্যবহার করবে তার উদাহরণ দিতে পারেন? DOM উপাদান উপস্থিত থাকলে আমার কার্যকর করা যেখানে আমার jquery নির্বাচনকারী বা কোড স্থাপন করব তা নিশ্চিত নয়।
সুপারদোপারেরো

1
@ সুপারডুপারেরো আমি সহজ উদাহরণ দিয়ে একটি উত্তর দিয়েছি। এটি পরীক্ষা করে দেখুন। 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
প্লাগিনের জন্য আপনাকে ধন্যবাদ। আমি এটি কাঁটাচামচ করে কিছুটা উন্নত করেছি। আমার আপডেট থেকে আপনি যা খুশি তা নিরবহার করুন। আমার পরিকল্পনা রয়েছে আরও কিছু উন্নতি, স্থির: আপডেট প্লাগইন
ব্র্যান্ডন বেলভিন


4
এটি আপনার কীভাবে কাজ করে তা উল্লেখ করা উচিত: উপাদানটি উপস্থিত থাকলে (এ ব্যবহার করে window.setInterval) প্রতি 500 এমএস জিজ্ঞাসা করে এটি কাজ করে । MutationObserverউত্তরটি ভোট দেওয়ার মাধ্যমেও কার্যকর হয় কিনা আমি জানি না ...
ক্রীড়া

2
উপাদানটি ইতিমধ্যে পৃষ্ঠায় থাকলে এটি সঠিকভাবে কাজ করে না। এই ফাংশনটির যথাযথ সংস্করণটি এখানে: gist.github.com/PizzaBrandon/5709010
Roland Soós

2
;ফাংশন ( ;(function ($, window) {) এর শুরুতে কী ব্যবহার করবেন তা দয়া করে ব্যাখ্যা করতে পারেন ?
মৃড

76

কোনও উপাদানের প্রদর্শনের জন্য অপেক্ষা করার জন্য এখানে একটি মূল জাভাস্ক্রিপ্ট ফাংশন।

পরামিতি:

  1. selector: এই ফাংশনটি $ {নির্বাচক element উপাদানটির সন্ধান করে
  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=5000এইচটিএমএল ট্যাগটির সন্ধান করবে যার id="div1"প্রতি 5000 মিলিসেকেন্ড।


নিস! আপনি কি এটি লিখতে পারেন যাতে কোনও নির্বাচককে গ্রহণ করা যায়?
mattsven

আমি এটি করতে পারি সন্দেহ করি .. তবে দয়া করে এলিমেটবাইকপাথটি পেতে এই পোস্টটি দেখুন: স্ট্যাকওভারফ্লো
এটিয়েন টোনিলিয়ার


1
পরিবর্তে পরিবর্তক পর্যবেক্ষক ব্যবহার করতে আপনি এটি লিখতে পারেন?
সুপারউবারডুপার

বা আপনি কি এই প্রতিশ্রুতি ব্যবহার করতে আবার লিখতে পারেন?
সুপারউবারডুপার

25

আপনি যখনই ডিওমে কোনও নতুন উপাদান যুক্ত হয়ে থাকেন তখন DOMNodeInsertedবা DOMSubtreeModifiedঘটনাগুলি শুনতে পান can

এছাড়াও লাইভক্যুরি jQuery প্লাগইন রয়েছে যা সনাক্ত করতে পারে যখন কোনও নতুন উপাদান তৈরি হবে:

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

1
খুব সুন্দর প্লাগইন! সরাসরি jquery এর মতো কোনও ফাংশন আছে? আমি ভাবছি যে এটি করার কোনও বিদ্যমান বৈশিষ্ট্য নেই। এবং যদি এটি প্লাগইন হয়, দয়া করে এই উত্তরের জন্য ভোট দিন;) আমার জন্য, এটি পুরোপুরি কার্যকর হয়। আপনাকে অনেক ধন্যবাদ.
স্যামুয়েল

1
দ্রষ্টব্য আই 9 9 ডোমনোডইনটেড প্রয়োগ করে তবে এতে একটি বড় বাগ রয়েছে যেখানে আপনি সময়ের জন্য কোনও উপাদান যুক্ত করার সময় এটি আগুন লাগবে না, যা আপনি যখন এটি ব্যবহার করতে চান তখন বেশিরভাগ সময় আসে। বিশদগুলি
মাইকমেকানা

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() {

});

দয়া করে মনে রাখবেন যে সার্ভারের কাছে অনুরোধ করার সময় উপাদানটি ডিওমে উপস্থিত থাকলে কেবল এটি কাজ করবে। যদি উপাদানটি জাভাস্ক্রিপ্টের মাধ্যমে গতিশীলভাবে যুক্ত করা হচ্ছে তবে এটি কার্যকর হবে না এবং আপনার অন্যান্য উত্তরগুলিও দেখার প্রয়োজন হতে পারে।


7
.ready()সবচেয়ে কিছুর জন্য ফাংশন কাজ করে (যদি কিছু নয়), শুধু document। এটা ঠিক পরিবর্তনশীল নির্মিত উপাদান, এমনকি উপর সাথে কাজ করবে না .live()
রিচার্ড নীল ইলাগান

7
রিচার্ড ইঙ্গিত হিসাবে @ বেরি, এটি কেবলমাত্র সার্ভারের কাছে প্রথম অনুরোধ করা হলে এইচটিএমএলে উপস্থিত থাকা উপাদানগুলির জন্য কাজ করে। জাভাস্ক্রিপ্টটি ডিওমে গতিশীলভাবে কোনও উপাদান যুক্ত করতে ব্যবহৃত হয়, এটি কাজ করে না।
চন্দ্রনশু

6
@ স্যাম, আপনি কী দয়া করে মেমরির উপাদানটির রেফারেন্সের সাথে এটি সংযুক্ত করবেন তা স্পষ্ট করে বলতে পারেন?
বিকাশ সিংহল

3
এই উত্তরটি ভুল। আপনি এখানে যা যাচাই করছেন তা নিয়মিত $(document).ready(), এটি উপাদান প্রয়োগ করে বলে আপনি মনে করেন না। এই বিশেষ শ্রোতা ঠিক কিভাবে কাজ করে। উদাহরণ
শিক্কেডিয়েল


14

আমি মনে করি যে এখনও সহজ এবং পঠনযোগ্য কাজের উদাহরণ সহ এখানে কোনও উত্তর নেই। DOM এর পরিবর্তনগুলি সনাক্ত করতে এইভাবে মিউটেশনঅবার্সারটি ব্যবহার করুন 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
এই উত্তরটি আইই 8-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");
    });
  });

উপাদানটি লোড হয়েছে কিনা তা দেখতে আমরা এখানে প্রতি 500 মিমি খতিয়ে দেখি, এটি যখন হয় তখন আমরা এটি ব্যবহার করতে পারি।

এটি বিশেষতঃ উপাদানগুলিতে ক্লিক হ্যান্ডলার যুক্ত করতে কার্যকর যা ডকুমেন্টটিতে গতিশীলভাবে যুক্ত হয়েছে।


8

InsertionQuery লাইব্রেরি সম্পর্কে কীভাবে ?

insertionQuery সিলেক্টর অ্যানিমেশন কলব্যাক ব্যবহার করে নির্বাচক (গুলি) এর সাথে সংযুক্ত যখন কোনও উপাদান তৈরি করা হয় তখন কলব্যাক চালানোর জন্য নির্দিষ্ট করা হয়। এই পদ্ধতিটি কলব্যাকগুলি চালানোর অনুমতি দেয় যখনই কোনও উপাদান তৈরি হয় কেবল প্রথমবার নয়।

গিথুব থেকে:

নোডগুলি দেখানোর জন্য নন-ডোম-ইভেন্টের উপায়। এবং এটি নির্বাচক ব্যবহার করে।

এটি কেবল বৃহত্তর ব্রাউজার সমর্থনের জন্য নয়, কিছু জিনিসের জন্য এটি ডিওএমটিউটেশনঅবার্সারের চেয়ে ভাল হতে পারে।

কেন?

  • কারণ ডিওএম ইভেন্টগুলি ব্রাউজারকে ধীর করে দেয় এবং ইনসারেশনকুয়েরি দেয় না
  • কারণ ডিওএম মিউটেশন পর্যবেক্ষকের ইনসারেশনকুইয়ের চেয়ে ব্রাউজার সমর্থন কম less
  • কারণ ইনসারেশনকিউরির সাহায্যে আপনি নির্বাচকরা ওভারহেড ছাড়াই ডিওএম পরিবর্তনগুলি ফিল্টার করতে পারবেন!

ব্যাপক সমর্থন!

IE10 + এবং বেশিরভাগ কিছুই (মোবাইল সহ)


7

এখানে এমন একটি ফাংশন রয়েছে যা মিউটেশনঅবার্সারের চারপাশে একটি পাতলা মোড়ক হিসাবে কাজ করে। একমাত্র প্রয়োজন ব্রাউজারটি মিউটেশনঅবার্সারকে সমর্থন করে; জিকুয়েরিতে কোনও নির্ভরতা নেই। একটি কাজের উদাহরণ দেখতে নীচে স্নিপেট চালান।

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

ভ্যানিলা জাভাস্ক্রিপ্টে কোনও প্রতিশ্রুতি ফেরানোর সমাধান এখানে রয়েছে (কোনও অগোছালো কলব্যাক নেই)। ডিফল্টরূপে এটি প্রতি 200 মিমি চেক করে।

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

এখানে একটি খাঁটি জাভাস্ক্রিপ্ট ফাংশন যা আপনাকে যে কোনও কিছুর জন্য অপেক্ষা করতে দেয়। কম সিপিইউ রিসোর্স নিতে ব্যবধানটি দীর্ঘতর করুন।

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

মিউটেশনঅবার্সার ব্যবহার করে একটি ক্লিনার উদাহরণ:

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("..."))
ম্যাটস্ভেভেন

@ ম্যাটসভেন ভাল পয়েন্ট! মিউটেশনগুলিতে কেবল নোডগুলি পরীক্ষা করা ডকুমেন্ট.কোয়ারিসিলেক্টর করার চেয়ে পারফরম্যান্স।
ইয়ং ওয়াং

দয়া করে বানানের ভুলটি সংশোধন করুন, ওয়েটফরএলম ওয়েটফর্মএলমে
ডালভীর

1

আপনি যদি এটির কিছুক্ষণ (সময়সীমা) দেখাশোনা বন্ধ করতে চান তবে নীচের jQuery কাজ করবে। এটি 10 ​​সেকেন্ড পরে শেষ হবে। খাঁটি জেএসের পরিবর্তে আমার এই কোডটি ব্যবহার করা দরকার কারণ আমার নামের মাধ্যমে একটি ইনপুট নির্বাচন করা দরকার এবং অন্যান্য সমাধানগুলির কিছু প্রয়োগ করতে সমস্যা হচ্ছিল।

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

আপনার যদি অ্যাসিঙ্ক ডোম পরিবর্তন হয় তবে এই কার্যটি ডিওএম উপাদানগুলির জন্য (সেকেন্ডে সময়সীমা সহ) পরীক্ষা করে, এটি ডিওএম এবং এর প্রতিশ্রুতি ভিত্তিক ভারী হবে না :)

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.