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 对上面的其余代码有很多依赖关系。

所以我考虑过使用延迟/承诺,但是如果 AJAX 不一定总是发生,我怎么能将代码作为承诺执行呢?

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 ... );
}

我想这就是你的基本问题,所以答案是“是”:-) 自己做。当然,如果您觉得它会发生很多,您可以将其定义为全球服务。

我想您也可以从您立即解决的合法构造的“延迟”对象开始。

于 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 回答