所以我已经对此进行了相当多的故障排除,并且正在撞墙。在大多数情况下,我非常熟悉承诺及其工作原理,并在一些项目中使用它们。我很难完成所有承诺,可以通过Google Calendar API调用不同的日历数据,并且脚本可以计算在回调函数中使用的结果数组的长度。以下是相关代码:
(function($){
var baseUrl = 'https://www.googleapis.com/calendar/v3/calendars/',
apiKey = 'xxxxxxxxxxxx',
calendarData = [],
events = [],
allCalendars = [],
eventsToDisplay = 9;
/* Get all the calendars that we have registered */
function getCalendars() {
return $.getJSON(ajaxurl, {action: 'wps_get_calendars'});
}
/* Get the events for a calendar by the calendar ID */
function getCalendarEvents(calendarID) {
return $.getJSON(baseUrl + calendarID + '/events', {
maxResults: '4',
orderBy: 'startTime',
timeMin: moment().format(),
singleEvents: true,
key: apiKey
}).success(function(data){
calendarData.push(data.items);
});
/* Create a collection of promises */
var promises = getCalendars().then(function(calendars){
var deferreds = [];
calendars.forEach(function(calendar){
deferreds.push(
getCalendarEvents(calendar.googleCalendarId)
);
});
return deferreds;
});
/* Wait until all the promises have completed, then sort the events */
$.when.apply($, promises).then(concatEvents);
})(jQuery);
基本上问题是在$.when
的最后一次调用,因为我在等待我必须完成的一系列承诺。 $.when
似乎没有工作,因为如果我尝试将calendarData
数组记录到$.when
回调中的控制台,它将返回一个没有计算长度的数组。我能够弄清楚如何做到这一点的唯一方法是在回调中使用setTimeout
,并将其设置为大约2000毫秒,但这不是理想的,因为取决于网络连接,API可用性,等等,接收所有数据的时间可能完全不同。
就像我在控制台中看到的一样,当我尝试将结果记录在$.when
回调中时,我得到了这个“无长度”数组,这个回调无法迭代,因为该剧本似乎认为它是空的:
知道我在这里做错了吗?提前感谢您的帮助。
答案 0 :(得分:0)
您的代码工作方式存在几个结构性问题。我发现的问题:
.success()
。使用.then()
。$.when()
返回一个解析为结果数组的单一承诺。$.when()
对于如何返回结果非常不满意。它将它们作为单独的参数返回,而不是作为结果数组返回(它不像ES6标准Promise.all()
那样工作)。$.when()
,则会与$.when()
进行非常奇怪的交互。getCalendar()
,以便它返回一个解析为日历数组的单一承诺,从而使其更易于使用。这可以为您提供所需的结果,并且它可以消除您依赖的一些更高范围的变量和副作用。
(function($){
var baseUrl = 'https://www.googleapis.com/calendar/v3/calendars/',
apiKey = 'xxxxxxxxxxxx',
events = [],
eventsToDisplay = 9;
/* Get all the calendars that we have registered */
function getCalendars() {
return $.getJSON(ajaxurl, {action: 'wps_get_calendars'}).then(function(calendars){
var promises = calendars.map(function(calendar) {
return getCalendarEvents(calendar.googleCalendarId);
});
return $.when.apply($, promises).then(function() {
// convert arguments to a single array as our resolved value
return [].slice.call(arguments);
});
});
}
/* Get the events for a calendar by the calendar ID */
function getCalendarEvents(calendarID) {
return $.getJSON(baseUrl + calendarID + '/events', {
maxResults: '4',
orderBy: 'startTime',
timeMin: moment().format(),
singleEvents: true,
key: apiKey
}).then(function(data){
// make resolved value be just data.items
return data.items;
});
/* get all calendars */
getCalendars().then(function(calendars){
// process array of calendars here
console.log(calendars);
});
})(jQuery);
此外,很容易对$.when()
的工作方式感到困惑。以下是一些解释它的一般信息。
$.when()
无法解析为一系列结果。相反,它将每个结果作为单独的参数传递给回调。所以,如果你有三个结果,那么就这样做:
$.when(p1, p2, p3).then(function(r1, r2, r3) {
console.log(r1, r2, r3);
});
然后,除此之外,jQuery Ajax调用也没有解析为单个值,它解析为三个值。所以,当你传递N jQuery ajax promises to $.when()
时,你得到了你的回调的N个参数,其中每个参数是一个包含三个值的数组(来自jQuery Ajax promise的三个值)。
因此,如果要在$.when()
中处理任意数量的promise结果,则必须使用传递给回调的arguments
对象并迭代它。
function processWhenResults() {
for (var i = 0; i < arguments.length; i++) {
// output each ajax result
// arguments[i] is an array of results for each corresponding ajax call
// arguments[i][0] is the actual Ajax result value
console.log(arguments[i][0]);
}
}
$.when.apply($, promises).then(processWhenResults);
或者,您可以像我在上面建议的代码中那样做,并将arguments对象转换为结果数组,以便您可以在其上使用普通的数组函数。
此外,.success()
已被弃用。你不应该使用它。请改用.then()
。
答案 1 :(得分:-2)
Haven没和他们玩过一段时间,但是你应该能够接受它并与它一起运行。
/* Create a collection of promises */
var control = $.Deferred();
var deferreds = [];
getcalendars().done(function(calendars){
calendars.forEach(function(calendar){
deferreds.push(
getCalendarEvents(calendar.googleCalendarId)
);
});
control.resolve();
});
control.done(function(){
/* Wait until all the promises have completed, then sort the events */
$.when.apply($, deferreds).done(function() {concatEvents}); })