2

私はこのコードのブロックを書く方法を理解するのが難しいです...

function myFunction(x,y,z) {
  // do some stuff here (code block A)

  // then some stuff here (code block B)

  // but... 
  if (y == 73) { // y isn't always 73...
    // I need more data from the server before I can complete this function
    $.getJSON("data.php", {y: 73, z: z}, function(data) { ... });
  }

  // and finally some other code down here (code block C)

  // And done!
  $.post("data.php", {data: someVariable}, callbackFx);
}

したがって、私が抱えている概念上の問題は、指定された入力に対してサーバーからより多くのデータを取得する必要があることに気付いた後、実行したいコード(コードブロックC)があることです。それはいつも起こるわけではありませんが、私は本質的に実行を一時停止したいと思います。そして、私たちは皆、同期AJAXが犯罪であり、Javascriptの神々からむち打ちをすることで罰せられることを知っています。

最初は、コードブロックCはそれ自体の関数に入れるべきだと思いましたが、コードブロックCには上記の残りのコードに多くの依存関係があるため、面倒になります。

そこで、deferred / promiseを使用することを考えましたが、AJAXが常に発生するとは限らない場合、promiseとしてコードを実行するにはどうすればよいですか?

if (y == 73) {
  var deferred = $.getJSON("data.php", {y: 73, z: z}, function(data) { ... });
  deferred.always(function() { ... });
}
else {
  // that function in the deferred never gets called
}

私が考えることができる「良い答え」に最も近いのは次のとおりでした(しかし、それが実際に「良い答え」であるかどうかはわかりません)...

var codeBlockC = function() { ... };

if (y == 73) {
  var deferred = $.getJSON("data.php", {y: 73, z: z}, function(data) { ... });
  deferred.always(codeBlockC);
}
else {
  codeBlockC();
}

次に、スコープやクロージャなどに問題があります。何か案は?これについてどうやって行くのかを完全に再編成する必要がありますか?

4

3 に答える 3

3

より簡単な方法は、コード ブロック Cの機能を入れ子関数に配置することです。JavaScript にはレキシカル スコープがあるため、必要なすべてのデータを引き続き利用できます。

例えば:

function myFunction(x,y,z) {
  // do some stuff here (code block A)

  // then some stuff here (code block B)

  var codeBlockC = function() {
      // code in here can access all variables from code blocks A and B
      // everything after the potential Ajax call needs to be in here

      // and finally some other code down here (code block C)

      // And done!
      $.post("data.php", {data: someVariable}, callbackFx);
  };

  // but... 
  if (y == 73) { // y isn't always 73...
    // I need more data from the server before I can complete this function
    $.getJSON("data.php", {y: 73, z: z}, function(data) { 
        codeBlockC(); // execute as callback
    });
  } else {
      codeBlockC(); // execute immediately
  }
}
于 2011-11-16T19:19:45.610 に答える
2

いつでもダミーの約束から始めることができます。

var def = { always: function(f) { f(); } };
if (whatever) {
  def = $.get( ... whatever ... );
}

def.always(function() {
  $.post( ... whatever ... );
}

それがあなたの基本的な質問だったと思うので、答えは「はい」です:-)自分で作ってください。もちろん、それが頻繁に発生すると思われる場合は、それをグローバル サービスと定義することもできます。

すぐに解決できる正当に構築された「Deferred」オブジェクトから始めることもできると思います。

于 2011-11-16T19:14:15.190 に答える
1

lwburk の回答のシンプルさが気に入っていると思いますが、遅延メソッドとして機能する独自のメソッドを作成することもできます。これにより、より複雑な状況での柔軟性が向上します。これを設定する方法の詳細については、jQuery Deferred Object を参照してください。ただし、ここに例を示します。

function myFunction(x,y,z) {
    var deferredFunction;

    // do some stuff here (code block A)

    // then some stuff here (code block B)

     //define your own function that is deferred
    deferredFunction = function () { 
        var defer = $.Deferred(); 

        if (y == 73) {
            $.getJSON("data.php", {y: 73, z: z}, function(data) { 

                //your code... 

                defer.resolve();
            });
        } else {
            defer.resolve();
        }

        return defer.promise();
    }

    //now execute the your function and when it resolves execute the rest of the code
    deferredFunction().then(function () {

         // and finally some other code down here (code block C)

         // And done!
         $.post("data.php", {data: someVariable}, callbackFx);
    });
}
于 2011-11-16T19:52:58.637 に答える