图像加载循环IE7堆栈溢出在第0行

时间:2012-12-12 22:55:45

标签: javascript internet-explorer stack-overflow

我试图逐帧加载jpeg图像,以创建jpeg图像的序列动画。我正在尝试使用javascript在递归循环中加载它们。 我需要线性加载图像以实现动画的渐进式回放。 (在加载所有帧之前开始播放)由于函数的自然递归,我从IE得到Stack overflow at line: 0错误。 (我的真实代码加载超过60帧)

以下是我如何执行此操作的基本示例:

var paths = ['image1.jpg', 'image2.jpg', 'image3.jpg']; //real code has 60+ frames
var images = [];
var load_index = 0;

var load = function(){
    var img = new Image();
    img.onload = function(){
        if(load_index<=paths.length){
            load_index++;
            load();
        }else{
            alert('done loading');
        }
    }
    img.src = paths[load_index];
    images.push(img);
}

在调用加载的下一步时,似乎可以通过使用间隔为1的setTimeout来避免此错误。这似乎让IE在加载下一张图像之前“呼吸”,但降低了图像加载速度。

任何人都知道如何避免这种堆栈溢出错误?

http://cappuccino.org/discuss/2010/03/01/internet-explorer-global-variables-and-stack-overflows/

上面的链接建议将函数包装起来将其从window对象中删除将有助于避免堆栈溢出错误。但是我看到奇怪的是它只通过序列得到大约15帧然后就死了。

1 个答案:

答案 0 :(得分:0)

简单地说,在这种情况下不要使用递归函数,没有任何需要:

var paths = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var images = [];
var loads = [];

/// all complete function, probably should be renamed to something with a 
/// unique namespace unless you are working within your own function scope.
var done = function(){
  alert('all loaded');
}

var loaded = function(e,t){
  /// fallbacks for old IE
  e = e||Event; t = e.target||e.srcElement;
  /// keep a list of the loaded images, you can delete this later if wanted
  loads.push( t.src );
  if ( loads.length >= paths.length ) {
    done();
  }
}

var load = function(){
  var i, l = paths.length, img;
  for( i=0; i<l; i++ ){
    images.push(img = new Image());
    img.onload = loaded;
    img.src = paths[i];
  }
}

事实上,正如您所发现的那样,您目前使用的方法非常密集。相反,上述版本不会为每个onload侦听器(节省内存)创建新函数,并将触发与浏览器允许的一样多的并发加载(而不是等待每个图像加载)

(上述内容已经手动输入,尚未经过测试)

更新

啊,那么为什么你这样做会更有意义:)在那种情况下,你使用setTimeout的第一种方法可能是最好的解决方案(你应该可以使用超时) 0)。如果可以避免这种情况,仍然有重新安排事情的空间。以下可能会解决问题...

var paths  = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var images = []; /// will contain the image objects
var loads  = []; /// will contain loaded paths
var buffer = []; /// temporary buffer
var done   = function(){ alert('all loaded'); }

var loaded = function(e,t){
  e = e||Event; t = e.target||e.srcElement; loads.push( t.src );
  /// you can do your "timing/start animation" calculation here...
  /// check to see if we are complete
  if ( loads.length >= paths.length ) { done(); }
  /// if not fire off the next image load
  else { next(); }
}

var next = function(){
  /// current will be the next image
  var current = buffer.shift();
  /// set the load going for the current image
  if ( current ) { current.img.src = current.path; }
}

var load = function(){
  var i, l = paths.length, img;
  for( i=0; i<l; i++ ){
    img = new Image();
    img.onload = loaded;
    /// build up a list of images and paths to load
    buffer.push({ img: img, path: paths[i] });
  }
  /// set everything going
  next();
}

如果上面没有这样做,另一种解决问题的方法是逐步浏览路径列表,并附加一串图像标记(可以在屏幕外渲染)使用它自己的onload="next()"处理程序... next()将负责插入下一个图像。通过执行此操作,它可以将负载触发和后续加载事件切换到代码外部,并且可以绕过堆叠调用。