2011-11-06 16 views
11

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

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

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

しかし、このコードは動作します:

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

私は特にそれを最初の方法を行うことができるようにしたい - 私のファイルの先頭にファイルをロードし、その後にそこから私は必要なすべての機能を使用します。これが可能か、getScriptの仕組みを誤解していますか?

答えて

29

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

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

*最終的にあなたの希望のスタイルのように動作するコードを書くことができる有望な新しい方法については、この回答の最後にある更新を参照してください。

あなたはこのようなものであるコードで falseに設定 async設定で jQuery.ajaxを使用してそれを行うことができ

documentation状態として

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

myHelperFunction(); 

しかし

同期要求してもよいです一時的にブラウザをロックし、リクエストがアクティブな間にアクションを無効にします。

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

jQuery全体で頻繁に使用されるコールバックスタイルを採用する方がはるかに良い考えです。

function doStuffWithHelper() { 
    myHelperFunction(); 
} 

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

あなたが呼び出す前に、複数の依存関係をロードする必要がある場合:あなたが名前の関数にコードを置くことができ、いずれかの無名関数を使用する必要はありません

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

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

ご覧のとおり、このようなアプローチは畳み込まれ、維持不能になります。

複数の依存関係をロードする必要がある場合は、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 release、それを行うための別の純粋なjQueryの方法を提供します。 1.5の時点で、すべてのAJAX要求がDeferred Objectは、あなたがこれを行うことができます返す:

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

は、非同期要求なので、もちろんそれは、コールバックを必要とします。

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

これは、同時に両方のスクリプトをダウンロードしてのみ、コールバックを実行します:Deferredの作り方を使用すると、しかし、あなたは簡単に独自の複雑な追跡システムなしで、複数の前提条件スクリプトをロードし、これを拡張することができ$.when()を使用して、従来のコールバックシステムの上に巨大な利点を持っていますそれらの両方がダウンロードされた後は、上記のYepnopeの例によく似ています。


アップデート2014年3月30日

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

awaitは、待機中の非同期機能を使用して、Promiseを返します。真のES6 Promiseオブジェクトが必要な場合や、AJAX呼び出しから返されるjQueryのような約束の実装があれば、ブラウザの実装方法はわかりません。そして、先に進む前にダウンロードしてawaitするためにそれを使用することができます

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

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

あなたがいる場合はES6の約束が必要な場合は、約束を返す関数でjQuery.getScriptをラップする必要があります。実際にこのスタイルで書くことを決定した今日は、asycawaitを使用し、次にTraceurを使用してコードを現在のブラウザで実行されるコードに変換することができます。これを行う利点は、other useful new ES6 featuresも多く使用できることです。

+0

驚くほど包括的な答えです。 – GregL

+0

+!かなり完全な答え。 Howerever、jQueryをロードしたときに 'for..in'シンタックスを使ってなぜ反復していますか? –

+0

@ gion_13これは、内部から 'if(loadedScripts [prop] === false){'を返して関数を終了して、依存関係に依存する次のコードが実行されないようにします。 '$ .each'を使用した場合は、' return false'でループを早く停止させることができましたが、ループの後のコードを実行すると、ループの前に何らかのフラグを設定してループの後でチェックしなければなりませんそのコードが実行されないようにします。 'for..in'ループを使用して関数を終了すると、よりきれいです。それを今見て、辞書の代わりに私はちょうどカウントvarを使用し、代わりに全体のスクリプトと比較したでしょう。 –

2

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

あなたはコールバック関数を使用したくない場合は、元の形式でjQueryの$.ajax()機能を使用する必要があります(とgetScript()忘れる)、および同期として転送を設定します。

$.ajax({ 
    url: url, 
    dataType: "script", 
    async: false 
}); 
2

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

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

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

// ... 

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

BenMの提案は可能ですが、あなたは、単一の呼び出しを行っている場合を除き、スクリプトがmyHelperFunctionを呼び出す任意の他の方法が持って前にダウンロードしているという保証は存在しませんので、それは解決策として機能しませんmyHelperFunctionしますトリガーされました。

0

JSONPを使用している場合は最初の方がうまく動作します。私はそのように頻繁に行います。