这里是我尝试过的事情以及它们不起作用的原因:
1. SetTimeout选项:99.999%的时间,这是正确答案。事实上,在过去的十年中,我一直在指导JavaScript,我始终坚信可以重构代码以使用此选项,并且从未相信存在无法使用此选项的情况。好吧,我终于找到了一个!问题在于,因为我的函数是内联调用的,如果下一行在我的iFrame完成加载之前执行,它会完全禁用我的脚本,而自从我的脚本完成后,外部脚本就会继续运行。某种回调将无法工作。
2. “什么都不做”的循环:您使用while(// iFrame未加载){//什么也不做}这个选项。理论上,这不会返回,直到框架加载。问题在于,由于这占用了所有资源,因此iFrame永远不会加载。尽管这个技巧非常不专业,肮脏等等,但当您只需要内联延迟时,它会起作用,但由于我需要完成外部线程,因此不起作用。在FF中,几秒钟后,它会暂停脚本,并弹出一个警报,指示有一个无响应的脚本。当该警报出现时,iFrame能够加载,然后我的函数能够返回,但是让浏览器冻结10秒钟,然后要求用户正确解除错误是行不通的。
3.模型对话框:我受到了FF弹出窗口允许iFrame在停止执行函数的同时加载的启发,并且考虑到这一点,我意识到这是因为模态对话框是一种停止执行但允许其他线程继续的方式!太棒了,所以我决定尝试其他模态选项。像alert()之类的东西非常好用!当它弹出时,即使只有1/10秒,iFrame也能够完成,所有工作都很顺利。如果1/10秒不足够,我可以将模型对话框放入解决方案2的while循环中,这将确保iFrame及时加载。很甜美,对吧?除了我现在必须弹出一个非常不专业的对话框,让用户解除才能运行我的脚本。我与自己争论这个行动的成本/效益,但是然后我遇到了一个场景,在该场景中我的代码在单个页面上被调用了10次!在访问页面之前必须解除10个警报吗?那让我想起了90年代末的脚本骗子页面,这绝不是一个选项。
4. 有无数的延时脚本:
大约有10个jQuery延迟或睡眠函数,其中一些实际上开发得相当巧妙,但都不起作用。有几个原型选项,但同样没有找到能够解决问题的!还有十几个库和框架声称他们有我需要的东西,但遗憾的是他们都让我失望了。
我确信,由于内置的模态对话框可以停止执行,同时允许其他线程继续执行,必须有某种可访问代码的方式来完成同样的事情而不需要用户输入。
代码实际上有成千上万行,是专有的,因此我为您编写了这个问题的小例子供您参考。重要的是要注意,您唯一能够更改的代码位于onlyThingYouCanChange函数中
测试文件:
<html>
<head>
</head>
</html>
<body>
<div id='iFrameHolder'></div>
<script type='text/javascript'>
function unChangeableFunction()
{
new_iFrame = onlyThingYouCanChange(document.getElementById('iFrameHolder'));
new_iFrame_doc = (new_iFrame.contentWindow || new_iFrame.contentDocument);
if(new_iFrame_doc.document)new_iFrame_doc=new_iFrame_doc.document;
new_iFrame_body = new_iFrame_doc.body;
if(new_iFrame_body.innerHTML != 'Loaded?')
{
//The world explodes!!!
alert('you just blew up the world! Way to go!');
}
else
{
alert('wow, you did it! Way to go!');
}
}
var iFrameLoaded = false;
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
unChangeableFunction();
</script>
</body>
blank_frame.html:
<html>
<head>
</head>
<body style='margin:0px'>Loaded?</body>
</html>
这是我从回答者的想法中结合而成的答案!你们太棒了!
我被允许更改的函数的新源代码:
function onlyThingYouCanChange(objectToAppendIFrameTo)
{
iFrameLoaded = false;
iframe=document.createElement('iframe');
iframe.onload = new Function('iFrameLoaded = true');
iframe.src = 'blank_frame.html'; //Must use an HTML doc on the server because there is a very specific DOM structure that must be maintained.
objectToAppendIFrameTo.appendChild(iframe);
var it = 0;
while(!iFrameLoaded) //I put the limit on here so you don't
{
if (window.XMLHttpRequest)
{
AJAX=new XMLHttpRequest();
}
else
{
AJAX=new ActiveXObject("Microsoft.XMLHTTP");
}
if (AJAX)
{
AJAX.open("GET", 'slow_page.php', false);
AJAX.send(null);
}
else
{
alert('something is wrong with AJAX!');
}
//If I was able to put some sort of delay here that paused the exicution of the script, but did not halt all other browser threads, and did not require user interaction we'd be golden!
//alert('test'); //This would work if it did not require user interaction!
}
return iframe;
}
slow_page.php :
<?
usleep(100000);//sleep for 1/10th of a second, to allow iFrame time to load without DOSing our own server!
?>
我需要指出的是,我已经声明在那个函数之外没有其他东西可以更改,而添加php页面确实违反了这个“规则”,但在我的情况下,我能够做到这一点。如果我不能这样做,我可以调用blank_frame.html而不是slow_page.php,并且它只需要调用一次(每次框架加载2次),假设它响应时间与iFrame加载相同。如果由于某种原因iFrame加载速度较慢,则可能会调用2次(总共3次调用服务器)。
new Function(){ return code; }
与setTimeout
的回调函数结合起来吗? - meder omuraliev