Jak czekać, aż element będzie istniał?

236

Pracuję nad rozszerzeniem w Chrome i zastanawiam się: jaki jest najlepszy sposób, aby dowiedzieć się, kiedy powstaje element? Używając zwykłego javascript, z interwałem sprawdzającym, aż element będzie istniał, czy też jQuery ma jakiś łatwy sposób to zrobić?

mattsven
źródło
1
Wygląda na to, że każda dzisiejsza opcja (w tym z komentarzy) jest przestarzała lub niekompletna. Nie uwzględniają w pełni niesamowitego wkładu @ hughsk, argumentu zgodności. Tymczasem zalecałbym po prostu użyć aktualizacji Brandona w odpowiedzi Ryana dla ogólnej prostoty i mniejszego ryzyka narzutu, jak sądzę.
cregox
4
MutationObserver> DOM Mutation Events> setTimeout.
mattsven
2
Nie z miejsca, gdzie stoję. setTimeoutjest kompatybilny, prosty w implementacji, prosty w utrzymaniu i ma znikomy narzut.
cregox
setTimeout+ jQueryjest moim zdaniem mniej niż idealny z dwóch powodów: 1.) wzdęcia jQuery 2.) niepotrzebnie ręcznie sprawdzasz DOM w poszukiwaniu elementów, zdarzenia szybko biją tak szybko, 3.) zawsze będzie wolniejszy niż jakikolwiek natywny realizacja. Jeśli musisz zrobić coś w oparciu o obecność elementu dość szybko, zwłaszcza jeśli Twoim celem jest bezproblemowa obsługa, jest gorszy.
mattsven
3
Istnieją 3 rodzaje ludzi: ci, którzy potrafią liczyć i ci, którzy nie mogą. ; P
cregox

Odpowiedzi:

148

DOMNodeInsertedjest przestarzałe, podobnie jak inne zdarzenia mutacji DOM, z powodu problemów z wydajnością - zalecanym podejściem jest użycie MutationObserver do oglądania DOM. Jest obsługiwany tylko w nowszych przeglądarkach, więc powinieneś wrócić do niego, DOMNodeInsertedgdy MutationObservernie jest dostępny.

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()
Hughsk
źródło
50
Zawsze uważałem, że interfejs API MutationObserver jest nieco złożony, dlatego zbudowałem bibliotekę, Arriv.js , aby zapewnić prostszy interfejs API do nasłuchiwania tworzenia / usuwania elementów.
Uzair Farooq
15
Polecam korzystanie z doskonałej biblioteki @UzairFarooq github.com/uzairfarooq/arrive
Dennis
3
Należy zwrócić uwagę na dwie rzeczy: (1) Lepiej byłoby to zrobić, if (mutation.addedNodes.length)ponieważ if (mutation.addedNodes)nadal zwróciłoby wartość true, nawet jeśli jest to pusta tablica. (2) Nie możesz tego zrobić, mutation.addedNodes.forEach()ponieważ addedNodes to nodeList i nie możesz iterować przez nodeList za pomocą forEach. Aby znaleźć rozwiązanie tego problemu, zobacz toddmotto.com/ditch-the-array-foreach-call-nodelist-hack
thdoan
3
Czy możesz podać przykład, w jaki sposób można tego użyć? Nie jestem pewien, gdzie umieścić mój selektor jquery lub kod, który chcę wykonać, gdy istnieje element DOM.
Superdooperhero
1
@Superdooperhero Odpowiedziałem łatwym przykładem. Sprawdź to. stackoverflow.com/a/57395241/6542186
SilverSurfer
113

Miałem ten sam problem, więc napisałem wtyczkę .

$(selector).waitUntilExists(function);

Kod:

;(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));
Ryan Lester
źródło
5
Dziękujemy za wtyczkę. Rozwidliłem i trochę poprawiłem. Zapraszam do wzięcia wszystkiego, co chcesz z mojej aktualizacji. Mam jeszcze kilka planowanych ulepszeń, wciąż: zaktualizowaną wtyczkę
Brandon Belvin
8
byłoby miło bez jquery dep ...;)
knutole
4
może powinieneś wspomnieć, jak to działa: działa, pytając co 500 ms, czy element istnieje (używając a window.setInterval). Nie wiem, czy MutationObserverodpowiedź zadziała również przez ankietę ...
sport
2
Nie działa poprawnie, jeśli element jest już na stronie. Oto odpowiednia wersja tej funkcji: gist.github.com/PizzaBrandon/5709010
Roland Soós
2
Czy możesz wyjaśnić, jakie jest zastosowanie ;na początku funkcji ( ;(function ($, window) {)?
mrid
76

Oto podstawowa funkcja JavaScript, która czeka na wyświetlenie elementu.

Parametry:

  1. selector: Ta funkcja szuka elementu $ {selector}
  2. time: Ta funkcja sprawdza, czy ten element istnieje co milisekundy $ {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);
            }
        }

Na przykład ustawiam selector="#div1"i time=5000będzie szukał znacznika HTML, którego id="div1"każde 5000 milisekund.

Etienne Tonnelier
źródło
Miły! Czy możesz to napisać, aby można było zaakceptować dowolny selektor?
mattsven,
Wątpię, czy dam radę. Ale proszę spojrzeć na ten post, aby uzyskać getElementByXpath: stackoverflow.com/questions/10596417/...
Etienne Tonnelier
1
Czy możesz napisać, aby zamiast tego używać obserwatora mutacji?
SuperUberDuper,
czy możesz przepisać ten, aby skorzystać z obietnicy?
SuperUberDuper,
25

Możesz słuchać DOMNodeInsertedlub DOMSubtreeModifiedzdarzeń, które są uruchamiane, gdy nowy element jest dodawany do DOM.

Istnieje również wtyczka jQuery LiveQuery, która wykrywa, kiedy tworzony jest nowy element:

$("#future_element").livequery(function(){
    //element created
});
serg
źródło
1
Bardzo fajna wtyczka! Czy jest taka funkcja w jquery bezpośrednio? Zastanawiam się, że nie ma takiej funkcji. A jeśli to jest wtyczka, proszę zagłosować na tę odpowiedź;) Dla mnie działa idealnie. Dziękuję Ci bardzo.
Samuel,
1
Uwaga IE 9 implementuje DOMNodeInserted, ale ma poważny błąd, w którym nie uruchamia się po dodaniu elementu na czas, który jest przez większość czasu, gdy chcesz go użyć. Szczegóły znajdują się na: help.dottoro.com/ljmcxjla.php
mikemaccana
23

Użyłem tego podejścia, aby poczekać na pojawienie się elementu, aby potem móc wykonać inne funkcje.

Powiedzmy, że doTheRestOfTheStuff(parameters)funkcję należy wywołać dopiero po the_Element_IDpojawieniu się elementu o identyfikatorze lub zakończeniu ładowania, możemy użyć,

var existCondition = setInterval(function() {
 if ($('#the_Element_ID').length) {
    console.log("Exists!");
    clearInterval(existCondition);
    doTheRestOfTheStuff(parameters);
 }
}, 100); // check every 100ms
główny
źródło
21

Możesz to zrobić

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

});

Należy pamiętać, że zadziała to tylko wtedy, gdy element będzie obecny w DOM, gdy zostanie o to poproszony z serwera. Jeśli element jest dynamicznie dodawany przez JavaScript, nie będzie działać i być może będziesz musiał spojrzeć na inne odpowiedzi.

Splynx
źródło
7
Ta .ready()funkcja działa na prawie wszystko (jeśli nie na nic), nie tylko document. Po prostu nie będzie działać z dynamicznie tworzonymi elementami, nawet na .live().
Richard Neil Ilagan
7
@Bery, jak zauważył Richard, działa to tylko w przypadku elementów, które są już obecne w kodzie HTML, gdy jest on najpierw żądany z serwera. Jeśli JavaScript jest używany do dynamicznego dodawania elementu do DOM, nie działa.
Chandranshu
6
@Sam, czy możesz wyjaśnić, jak dołączyć go do odwołania do elementu w pamięci?
Vikas Singhal
3
Ta odpowiedź jest niepoprawna. To, co tak naprawdę tutaj sprawdzasz, jest regularne $(document).ready(), a nie element, który Twoim zdaniem będzie miał zastosowanie. Właśnie tak działa ten specjalny słuchacz. Przykład
Shikkediel
1
To użycie nie jest zalecane zgodnie z api.jquery.com/ready
splintor
14

Myślę, że wciąż nie ma tu odpowiedzi na łatwy i czytelny przykład działania. Użyj MutationObserver, interface aby wykryć zmiany DOM, takie jak to:

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>

Uwaga: hiszpańskie dokumenty Mozilli na temat MutationObserversą bardziej szczegółowe, jeśli potrzebujesz więcej informacji.

Srebrny Surfer
źródło
2
Rozważ zostaw komentarz wyjaśniający powód oddania głosu, aby poprawić swoją odpowiedź. Dzięki.
SilverSurfer
12

Po prostu dodaj żądany selektor. Po znalezieniu elementu możesz uzyskać dostęp do funkcji wywołania zwrotnego.

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));
Diego Fortes
źródło
2
PossessWithin zgadzam się, że jest to bardzo czyste rozwiązanie i działa dla mnie.
jstafford,
3
Ta odpowiedź działa na IE8-10, a także na nowoczesnych przeglądarkach. Główny problem polega na tym, że będzie on działał, jeśli element nie istnieje - więc najlepiej, gdy masz pewność, że element tam będzie. W przeciwnym razie możesz dodać licznik.
W imieniu
1
Działa dla mnie idealnie
James Stewart
1
Działa jak urok !!
Aman
1
Były podobne, a nie identyczne. Ponadto wiele osób robi to samo. Na koniec sam kodowałem to rozwiązanie. To kiepskie rozumowanie, choć nawet w rzeczywistości tak byłbym wdzięczny za komentarz, który dałby mi znać. Odpowiedź rozwiązuje problem OP i nie ma widocznych motywów, które należy poddać ocenie.
Diego Fortes,
11

Dla prostego podejścia przy użyciu jQuery okazało się, że działa dobrze:

  // 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");
    });
  });

Tutaj po prostu sprawdzamy co 500 ms, aby zobaczyć, czy element jest załadowany, a kiedy jest, możemy go użyć.

Jest to szczególnie przydatne do dodawania procedur obsługi kliknięć do elementów, które zostały dynamicznie dodane do dokumentu.

Hedley Smith
źródło
8

Co powiesz na bibliotekę insertionQuery ?

insertionQuery używa wywołań zwrotnych Animacji CSS dołączonych do określonych selektorów, aby uruchomić wywołanie zwrotne podczas tworzenia elementu. Ta metoda umożliwia uruchamianie wywołań zwrotnych za każdym razem, gdy tworzony jest element, a nie tylko za pierwszym razem.

Z github:

Sposób na wychwycenie wyświetlanych węzłów bez zdarzenia w domenie. I używa selektorów.

To nie tylko dla szerszej obsługi przeglądarki, może być lepsze niż DOMMutationObserver dla niektórych rzeczy.

Czemu?

  • Ponieważ zdarzenia DOM spowalniają przeglądarkę, a funkcja wstawiania nie
  • Ponieważ DOM Mutation Observer ma mniejszą obsługę przeglądarki niż insertionQuery
  • Ponieważ dzięki insertionQuery możesz filtrować zmiany DOM za pomocą selektorów bez obciążania wydajności!

Szerokie wsparcie!

IE10 + i przeważnie wszystko inne (w tym mobilne)

b3wii
źródło
7

Oto funkcja, która działa jak cienkie opakowanie wokół MutationObserver. Jedynym wymaganiem jest to, że przeglądarka obsługuje MutationObserver; nie ma zależności od JQuery. Uruchom poniższy fragment kodu, aby zobaczyć działający przykład.

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>

Ivan Karajas
źródło
6

Oto obiecujące rozwiązanie w waniliowym JavaScript (bez niechlujnych wywołań zwrotnych). Domyślnie sprawdza co 200 ms.

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);
            }
        }
    });
}
blaster
źródło
5

Oto czysta funkcja Javascript, która pozwala na cokolwiek czekać. Ustaw interwał dłużej, aby zajął mniej zasobów procesora.

/**
 * @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);
}

Aby to nazwać, na przykład w jQuery, użyj czegoś takiego:

waitUntil(function(){
    return $('#myelement').length > 0;
}, function(){
    alert("myelement now exists");
}, function(){
    alert("I'm bored. I give up.");
});
Xgretsch
źródło
3

Rozwiązanie zwracające Promisei pozwalające na użycie limitu czasu (zgodny IE 11+).

W przypadku pojedynczego elementu (typ Element):

"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);
    });
}

W przypadku wielu elementów (wpisz 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);
    });
}

Przykłady:

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
});

Działa zarówno z listą elementów, jak i pojedynczym elementem.

Anwar
źródło
1
Moje ulubione rozwiązanie! Po co sprawdzać element instanceof HTMLElement? Czy może to być coś innego niż nulllub HTMLElement?
Leeroy
1
Podnosisz ciekawy punkt. Powinienem był rozszerzyć, używając Elementzamiast tego (naprawiony). Po prostu sprawdzam, ponieważ chcę mieć pewność, że zmienna elementma właściwość, innerHTMLjak stwierdza dokumentacja Element MDN . Możesz go usunąć, jeśli Cię to nie obchodzi!
Anwar
2

Czystszy przykład przy użyciu MutationObserver:

new MutationObserver( mutation => {
    if (!mutation.addedNodes) return
    mutation.addedNodes.forEach( node => {
        // do stuff with node
    })
})
Zaz
źródło
2

Jest to proste rozwiązanie dla tych, którzy są przyzwyczajeni do obietnic i nie chcą używać żadnych bibliotek ani timerów stron trzecich.

Od jakiegoś czasu używam go w swoich projektach

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
        });
    });
}

Aby go użyć:

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

lub za pomocą async / czekaj

const elm = await waitForElm('.some-classs')
Yong Wang
źródło
To jest miłe! Fajne jest to, że można go używać z async/ awaitteż. Być może będziesz w stanie wycisnąć z niego większą wydajność, robiącmutations.addedNodes.find(node => node.matchesSelector("..."))
mattsven
@mattsven Dobra uwaga! Sprawdzanie tylko węzłów mutacji jest bardziej wydajne niż wykonywanie document.querySelector.
Yong Wang
Popraw błąd w pisowni, watiForElm to waitForElm
dalvir
1

Jeśli chcesz, aby przestał się troszczyć po pewnym czasie (limit czasu), będzie działać następujący jQuery. Upłynie limit czasu po 10 sekundach. Musiałem użyć tego kodu zamiast czystego JS, ponieważ musiałem wybrać dane wejściowe według nazwy i miałem problem z implementacją niektórych innych rozwiązań.

 // 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);
S-Thomas
źródło
0

Zwykle używam tego fragmentu dla Menedżera tagów:

<script>
(function exists() {
  if (!document.querySelector('<selector>')) {
    return setTimeout(exists);
  }
  // code when element exists
})();  
</script>
Alejo JM
źródło
0

jeśli masz asynchroniczne zmiany w domach, ta funkcja sprawdza (z limitem czasu w sekundach) elementy DOM, nie będzie to trudne dla DOM i opartej na nim obietnicy :)

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 });
Meni Edri
źródło