【问题标题】:Javascript block script executionJavascript块脚本执行
【发布时间】:2010-02-17 14:26:40
【问题描述】:

我需要这样做:

  • 执行一段代码
  • 开始加载图片并阻止脚本执行
  • 加载图像后恢复执行
  • 执行其余代码

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

【问题讨论】:

    标签: javascript cross-browser execution


    【解决方案1】:

    阻止脚本执行的唯一方法是使用循环,这也会锁定大多数浏览器并阻止与您的网页进行任何交互。

    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
    

    话虽如此,我认为您应该考虑在不锁定浏览器的情况下实现目标的方法。

    【讨论】:

    • 我同意这是一种不好的方式,但我也认为这是唯一的方式。也许我可以让用户在加载图像时选择阻止脚本执行和调用加载函数。
    • @mck89:我很难相信这是唯一的方法。老实说,我在 JavaScript 中从未遇到过需要锁定脚本的情况。总有一种方法(例如临时覆盖函数)可以异步执行操作。毕竟,您可以控制页面上的脚本。也许您可以发布另一个问题来更详细地了解您的问题?
    • @mck89:complete 属性适用于 Gecko 和 IE,并且可能也适用于其他浏览器。如果您坚持阻止脚本执行,请参阅我的更新。
    • 是的,我想我会用这样的东西谢谢你的帮助。
    【解决方案2】:

    如果您不介意进行预处理步骤,请尝试Narrative Javascript,您可以这样做

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

    【讨论】:

    • 这是一个很棒的项目,但我正在尝试用纯 javascript 构建一个简单的应用程序......而且我对 Java 一无所知:)
    • @mck89:经过预处理后,您将获得纯 Javascript。
    • 是的,我知道,但我更喜欢只使用 javascript
    • 据我所知,Narrative JavaScript 所做的只是为您创建必要的回调。它不会停止脚本执行(因为脚本的其他部分仍然可以运行)。
    • @Andy:所以你认为 OP 想要一个检查循环 (while(!image.loaded){})?
    【解决方案3】:

    此建议并非您所要求的,但我将其作为可能的替代方案提供。

    使用您要使用的背景图像创建一个 CSS 类。当您的应用程序启动时,将此 CSS 类分配给一个 DIV,该 DIV 要么隐藏在站点外,要么按零像素调整为零。这将确保从服务器加载图像。当你想加载图像时(上面的第二步),使用你创建的 CSS 类;这将很快发生。也许足够快,您无需阻止后续代码执行?

    【讨论】:

    • 是的,这可能是一个很好的图像预加载方法,但我没有在应用程序开始时加载图像。
    • 我明白,但是如果您创建了一个带有 background-image 属性的 CSS 类,并将该类分配给一个虚拟 DIV,您将在应用程序的开头加载图像。
    【解决方案4】:

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

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

    例子:

    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;
       }
    }
    

    【讨论】:

    • 您确定可以使用 setTimeout 停止执行吗?
    • 这不会停止代码执行,它允许您等到图像加载完成后再进行任何工作。通过将剩余代码移动到 finishWork 函数中,您“停止”执行自己的代码。
    【解决方案5】:

    您可以使用 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 标头提供。否则,它的行为在不同的浏览器中可能会有所不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      • 2011-07-10
      • 1970-01-01
      • 2011-10-19
      相关资源
      最近更新 更多