我有一个从 3rd 方注入到我的页面的元素的属性:
document.querySelector('#embed-container #mf2-events').jsMF2
Run Code Online (Sandbox Code Playgroud)
jsMF2 被称为注入属性。我需要等到 jsMF2 属性被定义才能使用它。本来,我只是设置了一个超时时间,但是由于很多原因,这是不可取的。有没有办法可以旋转直到属性或设置回调?如果这是一个 C 程序,我会这样写:
while (document.querySelector('#embed-container #mf2-events').jsMF2 === undefined ||
document.querySelector('#embed-container #mf2-events').jsMF2 === null) { }
// do work
Run Code Online (Sandbox Code Playgroud)
您不希望忙等待,因为这样就没有其他 JavaScript 可以运行(更不用说浏览器 UI 的大部分),因此不会定义该属性。
理想情况下,提供该属性的任何内容都会触发一个您可以挂钩的事件。我假设你已经看过了,但没有找到。:-)
一旦在ECMAScript6最新的东西(又名“ES6”)的支持成为普遍的(它目前还不是),你可能能够使用Proxy这个(前提是您的目标浏览器允许Proxy在他们的HTML元素实例)。但是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);
}
}
Run Code Online (Sandbox Code Playgroud)
大多数浏览器会在 JavaScript 线程前几次可用时立即触发该计时器,然后将其限制为至少 4 毫秒的延迟以供后续调用使用。还是蛮快的。
不过,您不必过于激进。与计算机相比,人类的速度很慢,您可能会使用 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
旁注:查询
var document.querySelector('#embed-container #mf2-events');
Run Code Online (Sandbox Code Playgroud)
……有点奇怪。它说:给我在id mf2-events带有id embed-container. 但是页面上的id值必须是唯一的。所以真正说的是“获取#mfs-events元素,但前提是它在#embed-container元素内。”
除非这真的是你的意思,否则速度会更快
var document.getElementById('mf2-events');
Run Code Online (Sandbox Code Playgroud)
......将是要走的路。