为什么window.external.menuArguments.setTimeout不能通过IE上下文菜单工作

时间:2011-10-26 10:26:27

标签: internet-explorer settimeout setinterval

我正在为IE 6/7/8/9编写上下文菜单扩展。我使用window.external.menuArguments作为当前窗口对象。除了setTimeout / setInterval之外,这适用于大多数常见的api。我在IE 6-9中测试过它,setTimeout根本不起作用,setInterval在某些情况下导致内存耗尽。有没有解决方法,我错过了MSDN文档中的任何重要提示?

window.external.menuArguments.setTimeout(function() {
    alert("setTimeout OK");
},100);
window.external.menuArguments.setInterval(function() {
    alert("setInterval OK");
},100);

令人失望的IE在上面的测试代码中没有给我任何警告。

1 个答案:

答案 0 :(得分:0)

Microsoft通过外部为您提供的环境是一个有趣的野兽。实际上你有两个窗口,第一个包含external变量的窗口和你刚刚右键单击的目标浏览器窗口是通过external.menuArguments变量提供的。为了对话,我们将它们称为父窗口和子窗口,尽管它与window.open()调用的关系不同。

因此,在这种情况下,您有两个setInterval / setTimeout函数可供选择:

window.external.menuArguments.setTimeout(function first() { console.log('child'); }, 1);

window.setTimeout(function second() { external.menuArguments.console.log('parent'); }, 1);

但是这些功能都不会像你期望的那样执行,尽管出于不同的原因。

第一个将执行setTimeout,但它将传入一个函数引用,您的子窗口无法执行,因为函数本身是在父窗口中定义的。所以external.menuArguments无法调用first

第二个将执行setTimeout,而父window将引用second,因此它可以在下一个事件循环中调用该方法。但IE的外部功能并不会在退出之前从消息循环中抽取所有消息。因此,您的方法将排队,但代码将在第一个消息循环后退出。

您可以通过window.open('about:blank');打开一个新窗口来阻止父窗口立即退出,这将保持窗口运行,直到弹出过程完全加载。在我的笔记本电脑上,这给了我约600毫秒的间隔时间。

我正在尝试设计一个hack来保持进程运行,而不是像for / while循环一样死锁定消息循环。我的猜测是AJAX / FSO ActiveXObject领域会做的,但我还没有找到解决方案。我的情况要求父窗口进程永远执行,所以如果找到解决方法,我会回发。

很有趣,只是在setTimeout之后调用alert()将在我的间隔小于10毫秒时运行setTimeout回调,因此在释放父窗口进程之前显示警报需要几毫秒。

另一个痛点是,对于遗留目的,JS引擎是版本7或8,因此父实例中没有JSON对象,这意味着如果使用external.menuArguments,对象序列化和反序列化将在两个实例之间具有不同的原型链而是.JSON对象。并且没有Object.keys()或该语言的任何其他现代补充。

这个领域的整个文档实际上非常稀疏,因此通常是对任何有用的试验和错误实验。