2010-02-17 62 views
5

我需要做这样的事情:的Javascript块脚本执行

  • 执行一段代码
  • 开始加载图像,并阻止脚本执行
  • 当图像被加载恢复执行
  • 执行代码的其余部分

我知道最简单的方法是在图像的onload事件指定功能然后执行函数中的其余代码,但是如果可能的话,我想要一个阻止脚本执行的“线性”行为,然后恢复它。 那么,是否有跨浏览器的方式来做到这一点?

回答

3

阻止脚本执行的唯一方法是使用一个循环,这也将锁定大多数浏览器和防止与你的网页的任何交互。

Firefox,Chrome,Safari,Opera和IE 全部支持complete属性,最终在HTML5中进行了标准化。这意味着您可以使用while循环停止脚本执行,直到图像完成下载。

var img = new Image(); 
img.src = "/myImage.jpg"; 
document.body.appendChild(img); 
while (!img.complete) 
{ 
    // do nothing... 
} 

// script continues after image load 

话虽这么说,我觉得你应该看看没有锁定了浏览器实现目标的途径。

+0

我同意这是一种糟糕的方式,但我认为这是唯一的方法。也许我可以给用户在阻止脚本执行和加载图像时调用加载函数的可能性。 – mck89

+0

@ mck89:我很难相信这是唯一的方法。我可以诚实地说,我从来没有遇到JavaScript需要锁定脚本的情况;总是有一种方法(比如临时覆盖函数)异步执行任务。毕竟,您在页面上控制脚本。也许你可以发布另一个问题,更详细地讨论你的问题? –

+0

@ mck89:'完整'属性存在Gecko和IE,并可能在其他浏览器中工作。如果您坚持阻止脚本执行,请参阅我的更新。 –

1

如果你不介意的预处理步骤,尝试Narrative Javascript,您可以

image.onload = new EventNotifier(); 
image.onload.wait->(); 
+0

这是一个伟大的项目,但我试图在纯JavaScript中构建一个简单的应用程序......并且我不知道Java的任何内容:) – mck89

+0

@ mck89:预处理后,您将获得纯Javascript。 – kennytm

+0

是的,我知道,但我更喜欢只使用JavaScript – mck89

1

这个建议不完全是你要求的,但我提供它作为一个可能的选择。

用你想要使用的background-image创建一个CSS类。当你的应用程序启动时,将这个CSS类分配给一个DIV,该DIV可以隐藏在站点之外或大小为零零像素。这将确保图像从服务器加载。当你想加载图像(上面的第二步)时,使用你创建的CSS类;这会很快发生。也许足够快,你不需要阻止后续的代码执行?

+0

是的,这可能是一个很好的图像预加载方法,但我没有在应用程序的开始加载图像。 – mck89

+0

我明白了,但是如果您创建了具有背景图像属性的CSS类,则将该类分配给虚拟DIV,您将在应用程序开始时加载图像。 – Upperstage

1

我不会尝试完全阻止脚本执行,因为这可能会导致浏览器变慢,甚至会提醒用户脚本执行时间过长。

你可以通过使用事件来完成工作来“线性化”你的代码。您将需要添加一个超时功能,因为图像可能永远不会加载。

实施例:

var _img = null; 
var _imgDelay = 0; 
var _finished = false; 

function startWork(){ 
    _img = document.createElement('img'); 
    _img.onload = onImgLoaded; 
    _img.src = 'yourimg.png'; 

    // append img tag to parent element here 

    // this is a time out function in case the img never loads, 
    // or the onload event never fires (which can happen in some browsers) 
    imgTimeout(); 
} 

function imgTimeout(){ 
    if (_img.complete){ 
     // img is really done loading 
     finishWork(); 
    } 
    else{ 
     // calls recursively waiting for the img to load 
     // increasing the wait time with each call, up to 12s 
     _imgDelay += 3000; 

     if (_imgDelay <= 12000){ // waits up to 30 seconds 
     setTimeout(imgTimeout, _imgDelay); 
     } 
     else{ 
     // img never loaded, recover here. 
     } 
    } 
} 

function onImgLoaded(){ 
    finishWork(); 
} 

function finishWork(){ 
    if (!_finished){ 
     // continue here 
     _finished = true; 
    } 
} 
+0

你确定你可以用setTimeout来停止执行吗? – mck89

+0

这不会停止代码执行,它允许您等到图像完成加载后再做更多工作。通过将剩余的代码移入finishWork函数,您可以“停止”自己的代码执行。 – FlashXSFX

1

可以使用XMLHttpRequest和使用同步模式。

var url = "image.php?sleep=3"; 
var img = new Image; 
var sjax = new XMLHttpRequest(); 
img.src = url; 
sjax.open("GET", url, false); 
sjax.send(null); 
alert(img.complete); 

这里的窍门是我们加载相同的图像两次,第一次使用Image对象,并且还通过在同步模式中使用AJAX。 Image对象不是必需的,我只是假设你想要加载它。关键是如果ajax完成,那么图像将被完全下载到浏览器的缓存中。因此,该图像也可供Image对象使用。

这确实假定图像是与缓存友好的http头一起提供的。否则,它的行为在不同的浏览器中可能会有所不同。