2

正しく動作しない次のスクリプトがあります。

function getWidgetContent( widget ) {
    if(widget.script!=null){
        $global_widget_id = widget.widget_id;
        $.getScript( "js/" + widget.script, function() {
            $( ".widget_header_title_" + widget.widget_id ).append( widget.title );
        });
    }
}

これは次のように呼ばれます。

for ( j = 0; j <= widget_data.d.length - 1; j++ ) {
    getWidgetContent( widget_data.d[j] );
}

$.getScriptこれにより、関数内で関数が実行され、グローバル値に値が割り当てられ、ループの反復ごとに実行されると思いました。しかし、それは起こっていません。ループが終了するまでループを反復しているように見えます.3回ループし、毎回、つまり3回グローバル値に値を割り当ててから、最後に$.getScript.

もちろん、$.getScript ファイルのグローバル値の最後の割り当てを 3 回しか使用しないため、これは機能しません...

これを変更してグローバル変数に値を代入し、$.getScript. 完了したら、元のループを続行し、次の値をグローバル変数に割り当て、$.getScriptループが終了するまで実行します。

4

7 に答える 7

1

他の人の答えを見ると、私は自分でしか考えることができません。実装を変更します。

 $.getScript( "js/" + widget.script, function() {
     $( ".widget_header_title_" + widget.widget_id ).append( widget.title );
 });

対応するajax呼び出しに対して、ただし非同期ではない

$.ajax({
  url: "js/" + widget.script,
  dataType: "script",
  async: false,
  success: function() {    
      $( ".widget_header_title_" + widget.widget_id ).append( widget.title );    
  }
});
于 2012-12-15T01:15:15.267 に答える
1

getScript メソッドは非同期であるため、スクリプト値を含むサーバーからの応答を取得する前に、ループが次の反復を実行
するため、コールバック関数を送信する必要があります。javascript は、サーバーが応答したら何をすべきかを知っています。したがって、通常のループはここでは役に立ちませんが、再帰関数を使用できます。コールバック関数を取得して loopFunc を呼び出し、コレクション/配列内の次のアイテムに移動します。これがあなたにインスピレーションを与えることができることを願っています:

var getWidgetContent = function(wiget, loopFunc) {
  if(widget.script!=null){
    $global_widget_id = widget.widget_id
    $.getScript( "js/" + widget.script, function() {
        $( ".widget_header_title_" + widget.widget_id ).append( widget.title )
        loopFunc() //now we got a response from the server and want to move on to the next script tag.
    })
  }
}

var i = 0
(function loopFunc(){ //we define a function and call it instantly
  if(i < widget_data.d.length){ 
    getWidgetContent(widget_data.d,loopFunc) //now we call the getWidgetContent but we send in the current function aswell
    console.log($global_widget_id) // this is going to change each time
    i += 1
  }
}())
于 2012-12-07T12:44:07.977 に答える
1

getWidgetContent 実行してgetScriptgetScriptますが、ネットワーク (CPU に比べて比較的遅い) がスクリプトの取得を完了するのを待つ代わりに、すぐに戻ります。これはバグではありませんが、すばらしいことです。非同期プログラミングを使用すると、CPU で多くの作業を行うことができ、CPU よりもはるかに遅い処理を待つ必要がなくなります。 !

あなたの質問に答えるには:

  • スクリプト要求が完了したときにグローバル変数を設定するには、変数の割り当てをコールバック関数に移動するだけです。
  • すべてを一度に実行できるようにするだけで高速になりますが、最初のウィジェットが終了するまでgetScripts2 番目の開始を許可できない場合は、1回だけ呼び出して、コールバックで次のウィジェットを決定し、それを使用して再度呼び出します。getScriptgetWidgetContentgetWidgetContent
于 2012-12-17T03:06:27.987 に答える
1

$.getScript は非同期メソッドであるため、これを取得しています。この場合、スクリプトのロードが完了する直前にメソッドが戻り、その後もコードの実行を継続することを意味します。

これが意味することは、次のようなものです。

$.getScript('a.js', function () {
    console.log('Loaded a');
    }); 
$.getScript('b.js', function () {
    console.log('Loaded b');
    }); 
$.getScript('c.js', function () {
    console.log('Loaded c');
    }); 
// Output could be:
// Loaded c
// Loaded a
// Loaded b

これは、すべてのスクリプト ファイル リクエストを同時に実行できることを意味しますが、順序が確定的ではない (固定されている) ことも意味します。

Promise を使用する

jQuery 1.5 以降を使用している場合は、promise をgetWidgetContentチェーンすることで が順次呼び出されるようにすることができます。ただし、この方法の落とし穴は、すべてのスクリプト リクエストを同時にロードしないことです。リクエストは、前のリクエストが完了した後に次々と送信されます。

Deferred Objectである $.getScript の結果を返すようにしてください(ここでは最小限の変更を行いました。returnステートメントに注意してください)。

function getWidgetContent( widget ) {
  if(widget.script!=null){
    $global_widget_id = widget.widget_id;
    return $.getScript( "js/" + widget.script, function() {
        $( ".widget_header_title_" + widget.widget_id ).append( widget.title );
        });
  }
  return null;
}

前の promise が満たされた (前のアクションの完了) 後に新しい getWidgetContent を実行する新しいメソッド:

function doGetWidgetContentAfter(promise, widget) {
  return promise.then(function () {
      return getWidgetContent( widget );
      });
}

それを呼び出す:

var promise = $.when(true);
for ( j = 0; j <= widget_data.d.length - 1; j++ ) {
  promise = doGetWidgetContentAfter( promise, widget_data.d[j] );
}

説明

doGetWidgetContentAfterつまり、上記promiseが完了したら、関数を呼び出します。このメソッドは、内部メソッド promise が完了すると完了する promise を返します。getWidgetContentwidgetthen

複雑に聞こえるかもしれませんが、いろいろ試してみてください。:)

于 2012-12-17T10:22:39.510 に答える
0

コードを順番に実行したくない場合は、少し書き直す必要があります。次の呼び出しgetScriptは、前の呼び出しがそのコールバックを呼び出すまで実行しないでください。これは、コールバックから呼び出すことで実行できgetWidgetContentます...

何かのようなもの:

function getWidgetContent(d, index) {
  var widget = d[index];
  if(widget.script!=null){
    $global_widget_id = widget.widget_id;
    $.getScript( "js/" + widget.script, function() {
        $( ".widget_header_title_" + widget.widget_id ).append( widget.title );
        if (index <= d.length - 1)
            getWidgetContent(d,index+1); //call the next one
    });
  }
}

//Start the calls
getWidgetContent( widget_data.d,0);
于 2012-12-17T10:40:14.757 に答える
0

それはあなたを助けることができるかもしれません.ループ内に関数を配置すると、それに含まれる変数を書き換えることができます.

私の意見では、次のようにします。

function getWidgetContent(widget) {
  if(w_script != null){
    // And make variable for make sure each values come
    // from parent function and not from `$.getScript`
    var w_script = widget.script;
    var w_widget_id = widget.widget_id;
    var w_title = widget.title;
    $.getScript( "js/" + w_script, function() {
        $( ".widget_header_title_" + w_widget_id ).append( w_title );
    });
  }
}

このケースは私に直面していますが、私はそれに直面しており$.ajax、上記のような変数を作成しようとしています成功したら電話してください、頑張ってください

于 2012-12-17T10:32:10.723 に答える
0

変数をウィンドウの名前空間に割り当ててみてください:

window.global_widget_id = "foo";

その後、次のように参照できます。

var myId = window.global_widget_id;

そしてそれを上書きします:

window.global_widget_id = "newId";

($変数割り当ての は、jQuery も混乱させる可能性があります。)(不正解です。最後の部分は無視してください。)

編集:

$.getScript()ファイルはグローバル スコープの一部ではないようです: jQueryの getScript - ファイルをメイン スコープに含めますか? .

$.getScript()埋め込みではなくコールバックから関数を呼び出して、document.ready()その方法で変数を渡すことができますか?

于 2012-12-07T11:39:12.123 に答える