jQuery.when 理解

Posted

技术标签:

【中文标题】jQuery.when 理解【英文标题】:jQuery.when understanding 【发布时间】:2011-07-13 22:26:13 【问题描述】:

我正在尝试使用jQuery.when 触发两个ajax 请求,然后在两个请求完成后调用某个函数。这是我的代码:

var count = 0;
var dfr;

var showData = function(data) 
    dfr.resolve();
    alert(count);
   // Do something with my data data received
;

var method1 = function() 
    dfr = $.Deferred();

    return $.ajax('localhost/MyDataService/DataMethod_ReturnsData', 
        dataType: "jsonp",
        jsonp: "$callback",
        success: showData
    );
;

var method2 = function() 
    return $.ajax('localhost/MyDataService/DataMethod_ReturnsCount', 
        dataType: "jsonp",
        jsonp: "$callback",
        success: function(data) 
            count = data.d.__count;
        
    );
;

$.when(method1(), method2())
    .then(showData());

但是,这并没有按预期工作。 method1 中的 Ajax 调用将返回要在 showData() 中使用的数据,method2 中的 Ajax 调用将返回要分配给 var count 并稍后在 showData() 中使用的计数。

但是当我触发上述代码时,method1 被调用,然后被调用 method2,然后 showDatashowData 中的数据保留为 'undefined'。我怎样才能通过$.when 实现这一点,据我所知,只有在执行返回$.promise 的两个函数时才会执行此操作。我希望两个 ajax 调用都应该并行调用,之后的结果会根据两个调用的结果显示。

【问题讨论】:

您根本不需要dfr = $.Deferred(),因为$.ajax() 返回的jqXhr 是延迟的。不确定这是否会解决这里的问题,但这绝对是不必要的。问题可能是您使用的是.then() 而不是.done() 我指的是 eric hynds [erichynds.com/jquery/using-deferreds-in-jquery/] 的帖子,他也使用了 $.when 然后回调。 只有在使用不直接处理 deferred 的对象时才需要。 Eric 的演示使用了一个计时器对象,因此他必须在计时器到期时手动“解析”他自己创建的延迟对象。就像马特说的那样,如果它是一个 AJAX 查询,你就不需要它。 从方法中删除成功并使用 $.when(m1(),m2()).then(m3) 和 m3 = function(data1, data2) @Guillaume86 :我尝试使用 m3 = function(data1, data2) 实现您的删除成功的建议,但是 data1 和 data2 的值都未定义。你可以在这里修改我的代码 [jsfiddle.net/f4hmL/3/] 以显示它是如何工作的..? 【参考方案1】:
function showData(data1, data2) 
    alert(data1[0].max_id);
    alert(data2[0].max_id);


function method1() 
    return $.ajax("http://search.twitter.com/search.json", 
        data: 
            q: 'ashishnjain'
        ,
        dataType: 'jsonp'
    );


function method2() 
    return $.ajax("http://search.twitter.com/search.json", 
        data: 
            q: 'ashishnjain'
        ,
        dataType: 'jsonp'
    );


$.when(method1(), method2()).then(showData);​

这是一个有效的jsFiddle

【讨论】:

那是 gr8。谢谢。然而,在我的内部代码中实现它之后,我看到的是,我得到的 data1 和 data2 相同。这意味着,我可以删除 data2 并使用 data1 对象。 Data1 是 [Object]、“success”、[Object]。第一个 [Object] 是我的第一个 ajax 调用的响应,“成功”是字符串,第二个 [Object] 是我的第二个 ajax 调用的响应。我可以将其评估为 data1[0].d。然而 data1[2].responseText 是第二次 ajax 调用的结果。为什么我们得到的是 responseText 而不是 data[2].d?有什么建议吗? 看起来很奇怪,data1应该是一个包含m1()成功回调参数的数组,data2是一个包含m2()回调参数的数组 在将多个 Deferred 对象传递给 jQuery.when 的情况下,该方法从一个新的“主” Deferred 对象返回 Promise,该对象跟踪所有 Deferred 的聚合状态通过。 引用自手册。 没有解释 master deferred 是如何明智地解决参数的,这是 2 年前提出的问题;) 小提琴不起作用。阻止来源为“fiddle.jshell.net”的框架访问来源为“jsfiddle.net”的框架。协议、域和端口必须匹配。【参考方案2】:

问题是您将showData() 传递给then(),而不是showData。您应该将对函数的引用传递给.then()

$.when(method1(), method2())
    .then(showData);

$.when(method1(), method2())
    .then(function () 
        showData();
    );

编辑

我整理了一个working demo。部分问题(至少在您发布的代码片段中)是没有名为$callback 的回调函数。部分问题在于回调名称 '$callback' 中的 $

所以,去掉 jsonp: '$callback' ajax 选项,让 jQuery 默认使用一个名为 callback 的回调函数,定义一个具有该名称的函数,然后一切正常。

【讨论】:

两种方法都试过了,还是一样。 showData 中的数据参数仍然是“未定义” 查看我的编辑。您的代码中至少还有 2 个其他问题。 是的,在我看来是正确的——如果你调用.then(showData()),它将立即执行showData,然后将其结果传递给.then。正如马特所说 - 传递函数引用。 非常感谢马特。在您的示例的帮助下,我在这里放置了一个工作示例 [jsfiddle.net/f4hmL/3/].【参考方案3】:

我对你的代码做了一点修改,让你更容易理解……我还没有测试过,请尝试一下

var count = 0;
function countResponse(data) 
    count++;
    if(count==2)
    
        // Do something after getting responce from both ajax request
    
;

var method1 = function() 
    return $.ajax('localhost/MyDataService/DataMethod_ReturnsData', 
        dataType: "jsonp",
        jsonp: "$callback",
        success: function(data) 
            countResponse(data)
        
    );
;

var method2 = function() 
    return $.ajax('localhost/MyDataService/DataMethod_ReturnsCount', 
        dataType: "jsonp",
        jsonp: "$callback",
        success: function(data) 
            countResponse(data)
        
    );
;

【讨论】:

这不会回答我的查询,因为 countReponse 将丢失任何一个数据,无论是计数还是实际数据,因为方法 1 和方法 2 中的 ajax 调用是异步的。以后执行的任何调用都会有数据,但第一个数据会丢失。 jQuery deferreds 的重点是让您不必在继续之前计算响应的数量。 同意前两个cmets。这根本不能回答这个问题——尤其是。因为它不使用 jQuery 延迟。 抱歉,Ashish 造成我的误解,因为您没有提到这两个响应都需要存储。

以上是关于jQuery.when 理解的主要内容,如果未能解决你的问题,请参考以下文章

jQuery.when() 是不是对这些函数调用进行排队?

jquery $.when() .then() 和 .done() 之间的区别

带有ajax数组的JQuery $.when [重复]

有条件地添加到 jQuery .when

JQuery when() done() then()

nodejs中jQuery.when()的等价物是啥?