javascript:等待元素的属性准备好继续
我有一个从第三方注入我的页面的元素属性:javascript:等待元素的属性准备好继续,javascript,Javascript,我有一个从第三方注入我的页面的元素属性: document.querySelector('#embed-container #mf2-events').jsMF2 jsMF2被称为注入属性。我需要等到定义了jsMF2属性之后才能使用它。最初,我只是设置了一个超时,但由于许多原因,这是不可取的。是否有一种方法可以旋转直到属性关闭或设置回调?如果这是一个C程序,我会这样写: while (document.querySelector('#embed-container #mf2-event
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
您不希望等待很忙,因为这样就没有其他JavaScript可以运行(更不用说浏览器UI的大部分),因此不会定义属性 理想情况下,无论提供该属性的是什么,它都会触发一个事件,您可以将其挂钩。我假设你已经找过了,但没有找到。:-) 一旦ECMAScript6(也称为“ES6”)中对最新内容的支持变得广泛(目前还没有),您就可以使用它(前提是您的目标浏览器允许在其HTML元素实例上使用代理)。但是对
Proxy
的足够广泛的支持需要几年时间,如果不是更长的话(而且Proxy
无法填充填充)。(在ES7中,您可以使用,但据推测,Proxy
(由当前[截至2015年6月]标准定义)将在ES7技术推出之前得到广泛支持。)
除非您可以使用代理服务器,否则定时器确实是处理这种情况的正确方法。如果必要的话,它可以是一个非常有攻击性的计时器
如果已知元素存在,但您正在等待属性:
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事件
,在具有id
嵌入容器
的元素中找到。但是id
值在页面上必须是唯一的。所以真正要说的是“获取#mfs events
元素,但前提是它位于#embed container
元素中。”
除非这真的是你的意思,否则速度越快
var document.getElementById('mf2-events');
…将是一种方法。唯一真正的解决方法是使用回调。属性是如何设置的?如果它是由ajax请求设置的,那么您需要添加一个函数作为请求参数,当请求得到满足时将运行该参数。您可能需要的主题是回调、异步JavaScript和可能的承诺,它们是异步回调的现代方法。有一些不太流行,后来用新标准取代了它们 但您应该选择或同时实现这两种方法
编辑:如果属性不是dom属性,也可以使用。您的意思是在多线程C程序中,您会这样做。浏览器中的JavaScript(除了用作web Worker时)实际上是在单个线程上运行的。您需要使用
setTimeout()
进行轮询,或者可以在现代浏览器中使用。在而循环中旋转只会锁定浏览器,它永远不会成功,因为没有其他代码可以运行以实际导致更改发生。@user3689167:对,但是如果程序是真正的单线程程序,它将永远忙着等待——因为没有任何程序有机会设置jsMF2。要在忙着等待时执行此操作,至少需要两个线程。我不确定如何设置该属性,它是通过第三方注入的,我无权访问该第三方请不要使用0设置超时。如果没有,它会烧电池CPU@DennisCheung:不,没有。显然,您不想永远这样做,但它只是在运行代码,就像任何其他程序运行代码一样。正确编码的setTimeout(…,0)
的用例非常常见。确实如此。CPU睡眠时间越长,电池电量越少wasted@DennisCheung:再一次:它只是在适当的时间运行代码,做一些有用的事情。这就是全部。(这比忙碌的等待危害要小得多。)请不要再讲“不烧CPU就烧电池”的废话。“不要烧电池,即使做一些有用的事情”的逻辑结论是什么都不做。没有上下文,在第三方做出更改之前,你不知道“运行代码”在做什么。这意味着,它可能是一些网络负载、UI动画、CPU进程(您试图从中窃取CPU时间的任何进程)或用户交互。在大多数情况下,它只是消耗CPU和浪费。我使用setTimeout,0,但只在“修复愚蠢的执行顺序”时使用它,这样我就不会再轮询了。jsMF2
不是突变观察者可以观察到的任何东西。这是expando的财产。变异观察者只能观察DOM更改。它从document.querySelector返回。这是一个家庭聚会。这是可以观察到的,试试看。是的,元素是DOM元素。这不会使expando属性成为可以观察到的DOM属性。想想看,你会告诉观察者要观察什么<代码>子列表
?它不是子节点<代码>属性
<代码>属性值<代码>属性过滤器?这不是一个属性<代码>字符数据<代码>字符数据旧值?这不是字符数据<代码>子树?再说一次,它不是一个节点。见鬼,即使是一些DOM定义的反射属性,也无法通过MutationObserver观察到,例如