12

別のjsファイル内の外部jsファイルからjavascript関数を使用する必要があります。これは基本的に私が試したコードです:

$.getScript('js/myHelperFile.js');
myHelperFunction();

これは機能しません-「myHelperFunctionが定義されていません」というエラーが表示されます。

ただし、このコードは機能します。

$.getScript('js/myHelperFile.js', function(){myHelperFunction();});

具体的には、最初の方法でそれを実行できるようにしたいと考えています。ファイルの先頭にファイルをロードしてから、必要な機能を使用します。これは可能ですか、それともgetScriptがどのように機能するかを誤解していますか?

4

4 に答える 4

32

「最初の方法」で実行することは、非同期操作のみをサポートしているため、現在*は不可能jQuery.getScriptです。したがって、呼び出された直後に戻ります。

スクリプトが呼び出そうとすると、スクリプトがダウンロードされる前に返されるためmyHelperFunction()、エラーmyHelperFunctionundefined発生します。

*この回答の下部にある更新を参照して、最終的に希望のスタイルとほぼ同じように機能するコードを記述できるようになる有望な新しいメソッドを確認してください。

次のようなコードで設定されjQuery.ajaxた設定でそれを行うことができます:asyncfalse

$.ajax({
  url: 'js/myHelperFile.js',
  async: false,
  dataType: "script",
});

myHelperFunction();

しかしドキュメントに記載されているように:

同期リクエストはブラウザを一時的にロックし、リクエストがアクティブな間はアクションを無効にする場合があります。

これは非常に悪いことです。提供しているサーバーのmyHelperFile.js応答が遅い場合(ある時点発生します)、要求が終了するかタイムアウトになるまで、ページは応答しなくなります。

jQuery全体で頻繁に使用されるコールバックスタイルを採用することをお勧めします。

$.getScript('js/myHelperFile.js', function () {
   myHelperFunction();
});

匿名関数を使用する必要もありません。コードを名前付き関数に入れることができます。

function doStuffWithHelper() {
   myHelperFunction();
}

$.getScript('js/myHelperFile.js', doStuffWithHelper);

myHelperFunctionコードを実行する前にすべての依存関係がダウンロードされているかどうかを確認するための何らかのシステムをセットアップしない限り、これを呼び出す前に複数の依存関係をロードする必要がある場合は機能しません。次に、すべての呼び出しにコールバックハンドラーを設定し.getScriptて、コードを実行する前にすべての依存関係が読み込まれていることを確認できます。

var loadedScripts = {
    myHelperFile: false,
    anotherHelperFile: false
};

function doStuffWithHelper() {
    // check to see if all our scripts are loaded
    var prop;
    for (prop in loadedScripts) {
        if (loadedScripts.hasOwnProperty(prop)) {
            if (loadedScripts[prop] === false) {
                return; // not everything is loaded wait more
            }
        }
    }

    myHelperFunction();
}

$.getScript('js/myHelperFile.js', function () {
    loadedScripts.myHelperFile = true;
    doStuffWithHelper();
});
$.getScript('js/anotherHelperFile.js', function () {
    loadedScripts.anotherHelperFile = true;
    doStuffWithHelper();
});

ご覧のとおり、この種のアプローチは複雑になり、保守が困難になります。

複数の依存関係をロードする必要がある場合は、 yepnope.jsなどのスクリプトローダーを使用してロードする方がよいでしょう。

yepnope( {
        load : [ 'js/myHelperFile.js', 'js/anotherHelperFile.js' ],
        complete: function () {
            var foo;
            foo = myHelperFunction();
            foo = anotherHelperFunction(foo);
            // do something with foo
        }
} );

Yepnopeは、コールバックを同じよう.getScriptに使用するため、使用したいシーケンシャルスタイルを使用することはできません。ただし、これは適切なトレードオフです。複数の同期jQuery.ajax呼び出しを連続して実行すると、メソッドの問題が悪化するだけだからです。


2013年12月8日更新

jQuery 1.5リリースは、それを行うための別の純粋なjQueryの方法を提供します。1.5以降、すべてのAJAXリクエストは遅延オブジェクトを返すため、次のことができます。

$.getScript('js/myHelperFile.js').done(function () {
   myHelperFunction();
});

非同期リクエストであるため、もちろんコールバックが必要です。ただし、Deferredsを使用すると、従来のコールバックシステムに比べて大きな利点があります。$。when()を使用すると、複雑な追跡システムを使用せずに、これを簡単に拡張して複数の前提条件スクリプトをロードできます。

$.when($.getScript('js/myHelperFile.js'), $.getScript('js/anotherHelperFile.js')).done(function () {
  var foo;
  foo = myHelperFunction();
  foo = anotherHelperFunction(foo);
  // do something with foo
});

これにより、両方のスクリプトが同時にダウンロードされ、上記のYepnopeの例のように、両方がダウンロードされた後にのみコールバックが実行されます。


更新2014-03-30

私は最近、あなたが使用したい種類の手続き型のように見えるが非同期のコードを将来有効にする可能性のある新しいJavaScript機能に気付いた記事を読みました!非同期関数awaitは、キーワードを使用してasync、非同期操作が完了するまで関数の実行を一時停止します。悪いニュースは、現在、2つのECMAScriptバージョンが離れているES7に含まれる予定であるということです。

awaitPromiseを返すのを待っている非同期関数に依存しています。ブラウザの実装がどのように動作するか、真のES6 Promiseオブジェクトが必要かどうか、またはjQueryがAJAX呼び出しから返すようなpromiseの他の実装で十分かどうかはわかりません。ES6 Promiseが必要な場合はjQuery.getScript、Promiseを返す関数でラップする必要があります。

"use strict";
var getScript = function (url) {
  return new Promise(function(resolve, reject) {
    jQuery.getScript(url).done(function (script) {
      resolve(script);
    });
  });
};

次に、それを使用してダウンロードし、await続行する前に:

(async function () {
  await getScript('js/myHelperFile.js');
  myHelperFunction();
}());

今日このスタイルで書くことに本当に決心している場合は、 Traceurを使用asycしてから、現在のブラウザーで実行されるコードにコードをトランスパイルすることができます。これを行うことの追加の利点は、他の多くの便利な新しいES6機能も使用できることです。await

于 2011-11-06T11:30:24.363 に答える
2

関数を単独で使用するgetScript()ことはできないと思います。問題は、スクリプトがAJAXを使用してロードされていることです(実際、getScript特別な$.ajax()関数の省略形です)。ブラウザーが次の行で関数を実行しようとしたときに、サーバーがまだファイルを返していない可能性があります。

コールバック関数を使用したくない場合は、jQuery$.ajax()関数を元の形式で使用し(そして忘れてくださいgetScript())、転送を同期として設定する必要があります。このようにして、コードの実行を続行する前にスクリプトがロードされることを確認できます。

$.ajax({
    url: url,
    dataType: "script",
    async: false
});
于 2011-11-06T09:46:10.037 に答える
2

$ .getScript、および実際にはすべてのHTTP OP関連のjQuery関数は、デフォルトでは非ブロッキング呼び出しです。つまり、操作の完了中にコードがハングすることはありません。これが意味するのは、メソッドを実行しようとする行が実行される前に$ .getScriptがスクリプトをロードする方法がないため、上記のコードは間違いなく失敗するということです。これが、コールバック関数がパラメーターとして受け入れられる理由です。

しかし、あなたがやろうとしていることは可能です。スクリプトがロードされると、どこからでも呼び出すことができるはずです。スクリプトがダウンロードされる前にメソッドが呼び出されないようにするために必要なのは、必要なフラグを設定することだけです。

var HelperFileLoaded = false; 
$.getScript('js/myHelperFile.js', function() { HelperFileLoaded = true; });

// ...

function btnSaveClick() {
    if(!HelperFileLoaded) return;
    myHelperFunction(); 
}

BenMの提案は可能ですが、myHelperFunctionを1回だけ呼び出す場合を除いて、myHelperFunctionを呼び出す他のメソッドがトリガーされる前にスクリプトがダウンロードされる保証がないため、ソリューションとして機能しません。

于 2011-11-06T09:48:25.870 に答える
0

JSONPを使用している場合、最初のものは正常に機能します。私はそのように頻繁に実行します。

于 2013-11-22T16:59:14.337 に答える