6218


全ての`<img>`のロードが完了した時点で処理をしたい、といった質問の回答において、`$.Deferred`を使った例が挙げられています。  
（以下 <https://ja.stackoverflow.com/questions/6086#comment5088_6127> よりコードを引用）

[code]

    $.fn.all_loaded = function () {
        var all_done = new Array();
        this.each(function () {
            if ( this.complete || this.readyState === 4) 
               return;
            var promise = new $.Deferred();
            all_done.push(promise);
            this.onload = function () {
                promise.resolve();
            }
        });
        return $.when.apply($, all_done);
    };
    
    $('.images').each( function(i, holder) {
        $(holder).find('img').all_loaded().done(function() {
            if( holder.onload) holder.onload.call( holder);
        });
    });
    
[/code]

このコードでは`complete`や`readyState`を用いたロード済みチェックを行った後にonloadイベントの設定を行っていますが、この間にロードが完了することでonloadが呼ばれない可能性はないのでしょうか。

試しにonloadイベントを設定する直前にダミーループを仕込んで時間をかけさせてみたところ、きちんとイベントは発火しているようなのですが、規格上の根拠がないものかと探しています。

// IE8では画像がキャッシュされている際に後から設定したonloadが呼ばれないという話が  
// あるようなので、逆にそれ以外では後から設定しても呼ばれるのが通例のような気はしますが。。


CC BY-SA 3.0
2015-02-10T01:11:48.700
6206
2015-02-10T03:26:11.147
2017-04-13T12:52:39.113
-1
8000
question
javascript html
img要素のonloadを動的に設定する際の挙動について


JavaScript 実行環境のシングルスレッド性の話になります。

Web ページ向け JavaScript の記述で楽なところは、 JavaScript
の実行環境が基本シングルスレッドで動くことです。これにより、あるメソッド内のコードが実行中に、別の部分のコードが別のスレッドによって同時に実行されるということがありません。

シングルスレッドによる動作は、イベント処理についても同じように適用され、そこに割り込み処理という概念はありません。画像の読み込みが実質並列処理で、読み込みが完了したからと言って、「ブラウザの対応する処理が完了したその時に、実行中の
JavaScript コードを割り込んで別の JavaScript コードが実行されることはない」です。

確かに、画像はブラウザによってマルチスレッドで読み込まれ、JavaScript
のあるコードが実行中に、画像の読み込みが完了しているでしょうが、「画像読み込み完了によって発生する `'load'`
イベント」には、現在実行中のコードが属するイベントハンドラ内のコードの実行が終了してから手がつけられます。

例えば、ページ内でイベントが次々と発生している中、 JavaScript コード(この場合 `mouseclick`
イベントハンドラ)の実行が終わらない場合は、以下の簡略図ように、その間に生成されたイベントが Pending で待ち状態になっていくことでしょう。

![イベントハンドラスタック（想像）](https://i.stack.imgur.com/EJvUb.png)

質問の `complete` プロパティの話に戻ります。 `<img>` の `complete` プロパティが `true` になるタイミングが
`<img>` で指定された画像が完了し `'load'`, `'error'`
イベントが発火する直前で、その変更がネイティブコードによってされるとすれば（ここはドキュメントで明確になっていない）、 JavaScript
のコードから見て、 現在 `complete` が `true` でさらに `onload` が将来呼ばれるということはないといえます。

参考:

  * MDN: [HTMLImageElement](https://developer.mozilla.org/en/docs/Web/API/HTMLImageElement)
  * Webkit: [WebCore/loader/ImageLoader.cpp](https://github.com/WebKit/webkit/blob/master/Source/WebCore/loader/ImageLoader.cpp#L275)


CC BY-SA 3.0
2015-02-10T03:21:08.423
6218
2015-02-10T03:26:11.147
2015-02-10T03:26:11.147
4978
4978
6206
answer