javascript:等待元素的属性准备好继续

时间:2015-07-31 16:03:01

标签: javascript

我有一个元素属性从第三方注入我的页面:

document.querySelector('#embed-container #mf2-events').jsMF2

jsMF2表示注入属性。我需要等到定义jsMF2属性才能使用它。最初,我只是设置了超时,但出于多种原因这是不可取的。有没有办法可以旋转到属性或设置回调?如果这是一个C程序,我会写这样的东西:

    while (document.querySelector('#embed-container #mf2-events').jsMF2 === undefined ||
           document.querySelector('#embed-container #mf2-events').jsMF2 === null) { } 

    // do work

3 个答案:

答案 0 :(得分:4)

您不希望忙碌等待,因为之后没有其他JavaScript可以运行(更不用说浏览器UI的大部分内容),因此该属性不会被定义。

理想情况下,无论提供该属性的是什么,它都会触发您可以挂钩的事件。我会假设你看起来并没有找到一个。 : - )

一旦对ECMAScript6(又称“ES6”)中最新内容的支持变得普遍(目前不是这样),您可能能够使用Proxy来实现此目的(提供您的目标浏览器在其HTML元素实例上允许Proxy。但是对Proxy的广泛支持将花费几年时间(如果不长)(并且Proxy无法填充/填充)。 (在ES7中,您可以使用Object.observe,但可能Proxy由当前[截至2015年6月]标准定义,在ES7技术出现之前将得到广泛支持。)

除非您可以使用Proxy,否则计时器确实是处理这种情况的正确方法。如有必要,它可以是一个非常积极的计时器。

如果已知元素存在,但您正在等待该属性:

check(function(element) {
    // It's there now, use it
    // x = element.jsMF2
});

function check(callback) {
    var element = document.querySelector('#embed-container #mf2-events');
    if (element && 'jsMF2' in element) {
        setTimeout(callback.bind(null, element), 0);
    } else {
        setTimeout(check.bind(null, callback), 0);
    }
}

当JavaScript线程在前几次可用时,大多数浏览器会立即触发该计时器 ,然后将其限制为至少4ms延迟以便后续调用。还是很快。

但是,你不必过于激进;与计算机相比,人类很慢,你可能会使用10秒,20秒甚至50毫秒。

如果任何机会不会出现该属性,您希望最终停止重复的setTimeout系列(一秒钟后,10秒后,30秒后,之后) 60秒,适合您的用例)。你可以通过记住你什么时候开始,然后干脆而不是重新安排它来做到这一点:

var started = Date.now();

check(function(element) {
    // It's there now, use it
    // x = element.jsMF2
});

function check(callback) {
    var element = document.querySelector('#embed-container #mf2-events');
    if (element && 'jsMF2' in element) {
        setTimeout(callback.bind(null, element), 0);
    } else {
        if (Date.now() - started > 1000) { // 1000ms = one second
            // Fail with message
        } else {
            setTimeout(check.bind(null, callback), 0);
        }
    }
}

旁注:查询

var document.querySelector('#embed-container #mf2-events');

......有点奇怪。它说:给我第一个元素,id mf2-eventsid embed-container的元素中找到。但id必须在页面上是唯一的。所以真正说的是“获取#mfs-events元素,但前提是它只在#embed-container元素内。”

除非那个真的你的意思,否则显着更快

var document.getElementById('mf2-events');

......将是要走的路。

答案 1 :(得分:0)

这里唯一真正的方法是使用回调。该物业如何设定?如果它是由ajax请求设置的,则需要添加一个函数作为请求参数,该参数将在满足请求时运行。您可能需要的主题是回调,异步JavaScript和承诺,这是异步马蹄莲的现代方法。

答案 2 :(得分:-1)

DOM Events不是很受欢迎,后来又用新标准MutationObserver取代。

但你应check if your target browser support it或同时实施两者。

编辑:如果属性不是dom属性,您也可以使用Object.observe()