我正在为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在上面的测试代码中没有给我任何警告。
答案 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()或该语言的任何其他现代补充。
这个领域的整个文档实际上非常稀疏,因此通常是对任何有用的试验和错误实验。