簡単に言えば、この状況では再帰関数を使用しないでください。必要はありません。
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();
}
上記の方法で解決しない場合、問題を回避する別の方法として、パスのリストを 1 つずつ調べて、DOM にイメージ マークアップの文字列 (画面外にレンダリングされる) を追加します。それは独自のonload="next()"
ハンドラーです...next()
次の画像を挿入する責任があります。これを行うことで、ロードのトリガーとそれに続くロード イベントをコードの外部に渡し、呼び出しのスタックを回避する必要があります。