tre*_*005 8 javascript delayed-execution
有一个JavaScript函数,我无法控制代码,它调用我编写的函数.我的函数使用DOM生成一个iFrame,定义它的src,然后将它附加到另一个DOM元素.但是,在我的函数返回之前,因此允许继续执行包含函数,必须完全加载iFrame.
以下是我尝试过的事情以及它们不起作用的原因:
1. SetTimeout选项:
99.999%的时间,这是答案.事实上,在过去十年中我一直在使用JavaScript进行指导,我一直坚持认为代码总是可以重构以使用这个选项,并且从不相信存在情况并非存在的情况.好吧,我终于找到了一个!问题是因为我的函数被内联调用,如果在我的iFrame完成加载之前执行了下一行,那么我的脚本完全是neuters,并且从脚本完成的那一刻开始,外部脚本继续.各种回调都行不通
2."无所事事"循环:
您使用的此选项(// 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>
Run Code Online (Sandbox Code Playgroud)
blank_frame.html:
<html>
<head>
</head>
<body style='margin:0px'>Loaded?</body>
</html>
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
slow_page.php:
<?
usleep(100000);//sleep for 1/10th of a second, to allow iFrame time to load without DOSing our own server!
?>
Run Code Online (Sandbox Code Playgroud)
我想要注意的是,我说除了该功能之外我没有什么可以更改,并且添加php页面确实违反了"规则",但在可能情况下我能够做到这一点.如果我无法做到这一点,我本可以调用blank_frame.html而不是slow_page.php,并且它应该只需要调用一次(因此每帧加载2次),假设它以相同的量响应时间作为iFrame加载.如果由于某种原因iFrame负载较慢,它可能会将其称为2ce(总共3次调用服务器)
注意,这非常 hacky,我不会在任何现实情况下使用它。除其他潜在问题外,如果流量足够,您最终可能会遭到 DDOS 攻击。
您可以通过进行非异步 (A)JAX 调用来创建睡眠功能。在某些较旧的浏览器中,这可能会冻结所有内容,但至少不需要任何类型的用户响应。
while (!iFrameLoaded)
{
if (XMLHTTPRequest) {
var request = new XMLHttpRequest();
} else {
var request = new ActiveXObject("Microsoft.XMLHTTP");
}
request.open('GET', 'anyoldfile.htm', false);
request.send();
// check if the iframe is loaded and set iFrameLoaded
}
Run Code Online (Sandbox Code Playgroud)