33

動的スクリプト読み込みを使用して、最初のページ読み込みの時間を短縮します。スクリプトで定義された関数とオブジェクトに確実にアクセスできるようにするには、スクリプトが完全に読み込まれていることを確認する必要があります。

私はこの目的のために独自の Javascript ライブラリを開発したため、さまざまなライブラリでどのように行われているかを調べて、このテーマについてかなり多くの調査を行いました。この問題に関する議論の中で、LABjsの作成者である Kyle Simpson 氏は次のように述べています。

LABjs (および他の多くのローダー) は、すべてのスクリプト要素に「onload」と「onreadystatechange」の両方を設定し、一部のブラウザーが一方を起動し、一部のブラウザーが他方を起動することを認識しています...

この例は、この記事の執筆時点での jQuery の現在のバージョンである v1.3.2 にあります。

// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
    if ( !done && (!this.readyState ||
    this.readyState == "loaded" || this.readyState == "complete") ) {
        done = true;
        success();
        complete();

        // Handle memory leak in IE
        script.onload = script.onreadystatechange = null;
        head.removeChild( script );
    }
};

これは最先端の技術ですが、Opera 9.64 の奇妙な動作を分析しているときに、この手法を使用すると、onload コールバックがあまりにも早く起動されたという結論に達しました。

この質問への回答として私自身の調査結果を投稿し、コミュニティからさらなる証拠とフィードバックを収集したいと思います.

4

5 に答える 5

9

Opera では、script.readyState プロパティは信頼できません。たとえば、readyState "loaded" は、スクリプトが Opera 9.64 で実行される前に発生する可能性があります。

Opera 9.64 と Opera 10 で同じテストを実行しましたが、結果は異なりました。

Opera 9.64 では、onreadystatechange ハンドラがスクリプトの実行前と実行後の 2 回起動されます。どちらの場合も readyState プロパティは "loaded" です。つまり、この値を信頼してスクリプトの読み込みの終了を検出することはできません。

# Fri Dec 18 2009 17:54:43 GMT+0100
# Opera/9.64 (Windows NT 5.1; U; en) Presto/2.1.1
Test for script.readyState behavior started
Added script with onreadystatechange handler
readystatechange: loaded
test1.js: Start
test1.js: Start of closure
test1.js: End of closure
readystatechange: loaded

Opera 10 では、onreadystatechange ハンドラーは "loaded" という値で 2 回起動されますが、どちらもスクリプトの実行後に発生します。

# Fri Dec 18 2009 18:09:58 GMT+0100
# Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.10
Test for script.readyState behavior started
Added script with onreadystatechange handler
test1.js: Start
test1.js: Start of closure
test1.js: End of closure
readystatechange: loaded
readystatechange: loaded

これらの異なる動作は、onreadystatechange が Opera でのスクリプトの読み込みの終了を検出する信頼できる方法ではないことを示しています。Opera は onload リスナーもサポートしているため、代わりにこの別のメカニズムを使用する必要があります。

これらのテストの結果に基づいて、onreadystatechange は Internet Explorer でのスクリプトの読み込みの終了を検出するためにのみ使用する必要があり、他のブラウザーでは設定しないでください。

于 2009-12-18T18:21:41.270 に答える
4

Firefox、Safari、および Chrome では、onreadystatechange ハンドラは呼び出されません。

onreadystatechange ハンドラー セットのみを含む動的スクリプトを作成して、短いテスト ケースを作成しました。

<script type="text/javascript" language="javascript">
bezen.log.info(new Date(),true);
bezen.log.info(navigator.userAgent,true);

// Activate logs
bezen.log.on();
bezen.log.info('Test for script.readyState behavior started');

var script = document.createElement('script');
script.src = 'test1.js';
script.onreadystatechange = function(){
  bezen.log.info('readystatechange: '+script.readyState);
};
document.body.appendChild(script);
bezen.log.info('Added script with onreadystatechange handler');
</script>

Firefox 2、Firefox 3、Firefox 3.5、Safari 3、Safari 4、および Chrome 3 のローカル ファイルでテストを実行したところ、同様の結果が得られました (ここでは FF 3.5 で記録されたログ)。

Fri Dec 18 2009 17:53:58 GMT+0100
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6
Test for script.readyState behavior started
Added script with onreadystatechange handler
test1.js: Start
test1.js: Start of closure
test1.js: End of closure

onreadystatechange が呼び出されることはありません。これらのブラウザーでは、onload リスナーのみがスクリプトの読み込みの終了を検出するのに役立ちます。onreadystatechange は必要ありません。

于 2009-12-18T18:01:13.527 に答える
1

Internet Explorerでは、スクリプトの終了後、onreadystatechangeハンドラーが期待どおりに起動します。

Internet Explorer 6、Internet Explorer 7、およびInternet Explorer 8で同じテストを実行しましたが、これら3つのブラウザー(ここではInternet Explorer 6で記録されたログ)で同様の結果が得られました。

Fri Dec 18 18:14:51 UTC+0100 2009
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Test for script.readyState behavior started
Added script with onreadystatechange handler
test1.js: Start
test1.js: Start of closure
test1.js: End of closure
readystatechange: complete

ここで、ローカルファイルを使用したテストでは、readyStateは常に「完全」であり、数ページの更新後も同じでした。

ただし、Nicholas C. Zakasによるこの投稿に記載されているように、さまざまな状況下で「ロード済み」と「完全」、または単に「ロード済み」を観察することもできます。

于 2009-12-18T18:11:15.317 に答える
1

インターネット エクスプローラー (9 でテスト中) は、readyState === 'loaded' のときに、スクリプトの準備が整っているとは限らないことがわかりました。このイベント ハンドラー (もちろん 9) onactivateを使用して成功しました。前に髪を抜いていました。

于 2012-03-23T15:34:55.293 に答える
0

Chrome でも同様の結果が得られます。

準備ができていない...

onload と onerror だけです。

于 2012-07-12T18:40:16.130 に答える