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
,然后 showData
将 showData
中的数据保留为 '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 理解的主要内容,如果未能解决你的问题,请参考以下文章