jQuery.when的后期绑定

时间:2013-11-29 03:45:56

标签: javascript jquery asynchronous deferred

我正在使用一个使用jQuery Deferred Objects的框架。

在我的代码中,应该成功执行一个异步操作,以便执行另一个异步操作。

function doOperation() {

    var def2mock = $.Deferred();
    var def1 = doSomeAsyncOperation().done(function () {
        var def2 = doAnotherAsyncOperation();
    });

   return $.when(def1, def2mock);
}

所以我把第二个操作的调用放在第一个操作延迟的“完成”承诺中,如例子中所示。 现在,我用函数doOperation包装这个序列。 doOperation的结果应该是两个异步调用的延迟的连接。如果所有异步操作都成功则意义doOperation成功,如果其中任何异步操作失败,则失败,这正是$.when所做的。

问题是为了使用$.when创建联接,我需要调用$.when时出现的延迟。并且因为此时第二个异步操作的延迟不可用,所以我必须首先找到创建连接的方法,然后将延迟的第二个异步操作添加到连接以后。 / p>

为此,我想我可以在$.Deferred中定义名为def2的新模拟 doOperation。当真正的def2准备就绪时,我可以某种方式链接真实的延迟到模拟的一个,即使真实的一个与模拟一个同步它的状态。我找到的唯一方法是做

def2.done(def2mock.resolve)
// and 
def2.fail(def2mock.reject)

但我不认为这种手动链接是正确的方法。

所以请告诉我你是否有更好的建议如何以正确的方式做到这一点。

2 个答案:

答案 0 :(得分:2)

  

当真正的def2准备就绪时,我可以某种方式链接真实延迟到模拟的那个,即使真实的一个与模拟一个同步。

这实际上是.then的作用:它返回一个新的promise,当从传递的回调中返回的promise被解析/拒绝时,它会被解析/拒绝。

为了使这项工作与$.when一致,您必须保留对原始承诺的引用:

function doOperation() {
  var def1 = doSomeAsyncOperation();
  var def2 = def1.then(function () {
    return doAnotherAsyncOperation();
  });
  return $.when(def1, def2);
}

DEMO

当回调返回的承诺被解析时,

def2将被解析,即doAnotherAsyncOperation返回的承诺。


但我不认为从概念的角度来看,使用$.when是一个不错的选择。您实际上正在执行顺序两个异步函数,但$.when用于在 parallel 中运行异步函数。

我只是通过.then链接函数调用并收集响应:

function doOperation() {
  return doSomeAsyncOperation().then(function (resp1) {
    return doAnotherAsyncOperation().then(function(resp2) {
      return [resp1, resp2];
    });
  });
}

DEMO

我会说doAnotherAsyncOperation之后执行doSomeAsyncOperation更加清晰,doOperation的来电者可以使用这两个来电的结果。

你可能必须为失败案例做类似的事情。

答案 1 :(得分:1)

我对Deferred没有任何经验(我也不完全理解它的作用),但是如果你只是想进行连锁操作,那会是这样吗?

function doOperation(operations) {
    var wrapper = {};
    wrapper.index = 0;
    wrapper.operations = operations;
    wrapper.onthen = $.proxy(function() {
        if (this.index < this.operations.length) {
            this.operations[this.index]().then(this.onthen);
        }
        this.index++;
    }, wrapper);
    wrapper.onthen();
}

以下是演示:http://jsfiddle.net/vz6D7/2/