我有以下代码:
var requestEvents = getEvents();
requestEvents.done(function (resp1) {
$(resp1).find('events').each(function() {
var event_id = $(this).find('id').text();
var event_name = $(this).find('name').text();
var event_description = $(this).find('description').text();
var event_start_date = $(this).find('startDate').text();
var event_end_date = $(this).find('endDate').text();
count++;
if (count >= 2) {
// This will execute after the first request is done
var requestParticipants = getParticipants(event_id);
var requestPlaces = getPlaces(event_id);
var requestMedia = getMedia(event_id);
$.when(requestParticipants, requestPlaces, requestMedia).done(function (resp2, resp3, resp4) {
participants.push(resp2[2].responseText);
media.push(resp3[2].responseText);
places.push(resp4[2].responseText);
var new_event = {
'id' : event_id,
'name' : event_name,
'description' : event_description,
'start_date' : event_start_date,
'end_date' : event_end_date,
'participants' : participants,
'pictures' : media,
'places' : places
};
events.push(new_event);
console.log(resp2[2].responseText);
console.log(resp3[2].responseText);
console.log(resp4[2].responseText);
});
}
});
});
一切都按预期工作,但是当.done中的代码完成后,我需要执行更多代码。
我试过
.then( function(){
});
但这会在所有事件都放入数组之前运行。
我需要等待所有事件放在事件数组中的东西,这个事件现在还没有发生。我怎样才能做到这一点?
ajax调用方法:
function getEvents(){
return $.ajax({
type:"GET",
url: "http://"+server+":"+port+"/remember-me/rest/events?user="+ user,
dataType : "xml"
});
}
function getParticipants(event_id){
return $.ajax({
type:"GET",
url: "http://"+server+":"+port+"/remember-me/rest/events/"
+ event_id + "/participants",
dataType : "xml"
});
}
function getMedia(event_id){
return $.ajax({
type:"GET",
url: "http://"+server+":"+port+"/remember-me/rest/events/"
+ event_id+ "/media",
dataType : "xml"
});
}
function getPlaces(event_id){
return $.ajax({
type:"GET",
url: "http://"+server+":"+port+"/remember-me/rest/events/"
+ event_id+ "/places",
dataType : "xml"
});
}
答案 0 :(得分:3)
最简单的方法?所有操作完成后,使用$.Deferred
生成您自己的延迟对象(终结器)和resolve
。基本上是:
var requestEvents = getEvents();
var finalizer = $.Deferred(); // ADDED
requestEvents.done(function (resp1) {
var unfinishedEvents = $(resp1).find('events').length; // ADDED
$(resp1).find('events').each(function() {
/* ... */
count++;
if (count >= 2) {
// This will execute after the first request is done
var requestParticipants = getParticipants(event_id);
var requestPlaces = getPlaces(event_id);
var requestMedia = getMedia(event_id);
$.when(requestParticipants, requestPlaces, requestMedia).done(function (resp2, resp3, resp4) {
/* ... */
})
.then(function(){ // ADDED
if (--unfinishedEvents == 0){ // ADDED
finalizer.resolve(); // ADDED
} // ADDED
}); // ADDED
}
});
});
finalizer.done(function(){ // ADDED
/* ... */ // ADDED
}); // ADDED
示例可以在这里找到:http://jsfiddle.net/j8o2y88z/3/(观察控制台)。要查看它随机化了多少事件,请参阅http://jsfiddle.net/j8o2y88z/4/
答案 1 :(得分:1)
编辑,使用单个函数定义单个$.ajax()
请求的方法;将请求设置存储在单个阵列中。 url
或其他参数(例如data
)传递给request
函数。利用.each()
的范围循环遍历设置数组,将数据推送到events
数组。当events
数组length
等于设置length
或requests
(jsfiddle urls
)length
时,请使用.always()
回调执行其他任务。
尝试
..
$.when(requestParticipants, requestPlaces, requestMedia)
.done(function (resp2, resp3, resp4) {
participants.push(resp2[2].responseText);
media.push(resp3[2].responseText);
places.push(resp4[2].responseText);
var new_event = {
'id' : event_id,
'name' : event_name,
'description' : event_description,
'start_date' : event_start_date,
'end_date' : event_end_date,
'participants' : participants,
'pictures' : media,
'places' : places
};
events.push(new_event);
console.log(resp2[2].responseText);
console.log(resp3[2].responseText);
console.log(resp4[2].responseText);
})
// `always` , or `complete` callback
// i.e.g., `10` : actual or expected `events` array` `.length`
.always(function() {
if (events.length === 10) {
// do stuff
// when `events` `.length` === total requests
console.log(events.length);
};
})
..
答案 2 :(得分:0)
如果布莱恩·克里斯蒂的回答是正确的,那么以下简化也将是正确的......并且显得更加优雅。
首先是一些目标:
$.Deferred()
unfinishedEvents
count
这里是以骨架形式的流量控制:
getEvents().then(function (resp1) {
return $.when.apply(null, jQueryCollection.map(function(item, i) {
...
return (i < 2) ? null : $.when(p0, p1, p2).then(function(a0, a1, a2) {
return {...};
});
}).get());
});
注意:
.done()
替换.then()
并进行适当的返回,允许渐进式过滤。 .done()
是一种死胡同的方法,虽然它本身具有功能,却不会对承诺链做出贡献 .get()
是必要的,因为jQueryCollection.map()
会返回另一个jQueryCollection。 完整的代码仍然相当简洁:
var promiseOfEvents = getEvents().then(function (resp1) {
return $.when.apply(null, $(resp1).find('events').map(function (event, i) {
var $event = $(event),
event_id = $event.find('id').text();
return (i < 2) ? null : $.when(getParticipants(event_id), getPlaces(event_id), getMedia(event_id)).then(function (a0, a1, a2) {
return {
'id' : event_id,
'name' : $event.find('name').text(),
'description' : $event.find('description').text(),
'start_date' : $event.find('startDate').text(),
'end_date' : $event.find('endDate').text(),
'participant' : a0[2].responseText,
'picture' : a1[2].responseText,
'place' : a2[2].responseText
};
});
}).get());
});
promiseOfEvents.then(function () {
// now compose `events` from the arguments
var events = [].slice.apply(arguments);
// work with `events` here
});
注意:
events
。即使使用原始代码,所需的数据也可以(并且应该)通过承诺链提供 participants
,media
和places
从来都不是必需的。即使使用原始代码,单个数据项也可以(并且应该)作为events
的属性包含在内,而不使用外部数组。