Как ждать, пока элемент не существует? - PullRequest
203 голосов
/ 02 апреля 2011

Я работаю над расширением в Chrome, и мне интересно: как лучше узнать, когда элемент появляется?Используя простой javascript, с интервалом, который проверяет, пока элемент не существует, или jQuery имеет какой-то простой способ сделать это?

Ответы [ 14 ]

3 голосов
/ 30 ноября 2015

Вот чистая функция Javascript, которая позволяет вам ждать чего угодно. Установите интервал, чтобы он занимал меньше ресурсов процессора.

/**
 * @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.");
});
2 голосов
/ 19 октября 2016

Более чистый пример с использованием MutationObserver:

new MutationObserver( mutation => {
    if (!mutation.addedNodes) return
    mutation.addedNodes.forEach( node => {
        // do stuff with node
    })
})
1 голос
/ 10 января 2019

Решение, возвращающее 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 HTMLElement) {
                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
});

Работает как для списка элементови один элемент.

0 голосов
/ 31 мая 2019

Просто добавьте нужный селектор. Как только элемент найден, вы можете получить доступ к нему в функции обратного вызова.

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));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...