I'm trying to get all of a user's events, for all of their calendars on Google Calendar. I'm doing this by first making the call to gapi.client.calendar.calendarList.list
, and then using the IDs retrieved in the call to gapi.client.calendar.events.list
. However, this is resulting in some very weird results. Here is the code:
getAllEvents: function() {
var deferred = $q.defer(),
// get all calendars that the user has on Google Calendar
getCalendars = function() {
gapi.client.load('calendar', 'v3', function() {
var request = gapi.client.calendar.calendarList.list({});
request.execute(function(resp) {
if(!resp.error) {
var calendarIds = [];
for(var i = 0; i < resp.items.length; i++) {
calendarIds.push(resp.items[i].id);
}
getEvents(calendarIds);
}
else {
deferred.reject(resp.error);
}
});
});
},
// get all events for each calendar that was found
getEvents = function(calendarIds) {
var events = [];
for(var i = 0; i < calendarIds.length; i++) {
// bind i to function to allow asynchronous functions inside for loop
(function(cntr) {
var request = gapi.client.calendar.events.list({
calendarId: calendarIds[i]
});
request.execute(function(resp) {
if(!resp.error) {
for(var j = 0; j < resp.items.length; j++) {
console.log(j);
events.push(resp.items[j]);
}
}
else {
deferred.reject(resp.error);
}
});
})(i);
}
console.log(events);
deferred.resolve(events);
};
// login to google API before making calls
gapi.auth.authorize({
client_id: this.clientId,
scope: this.scopes,
immediate: true,
}, getCalendars);
return deferred.promise;
}
This retrieves the calendar IDs correctly, and even retrieves all the events correctly. However, I think the way I'm doing the asynchronous calls is causing some problems. If I console.log
the events
array after the inner for loop, it has 110 items but a length of 0 and none of the items can be accessed via their index. If I console.log
something inside the for loop, it prints after the console.log(events)
. Lastly, if I console.log
the value of j
within the inner for loop, the values are logged out of order, say 0...19
, then 0...86
.
Any ideas what I am doing wrong here? Like I said, it's retrieving data correctly but I think something is going wrong with the asynchronous calls. Thanks
As I thought, the main reason for these strange errors was the use of the for loop with the asynchronous calls. In order to avoid the for loop, I decided to use Angular's promises more to my advantage:
$q.all
to make all of the calls using the promises created, THEN return all the events found.Here's the new code:
getAllEvents: function() {
var deferred = $q.defer(),
// get all calendars that the user has on Google Calendar
getCalendars = function() {
var calDeferred = $q.defer();
gapi.client.load('calendar', 'v3', function() {
var request = gapi.client.calendar.calendarList.list({});
request.execute(function(resp) {
if(!resp.error) {
var calendarIds = [];
for(var i = 0; i < resp.items.length; i++) {
calendarIds.push(resp.items[i].id);
}
calDeferred.resolve(calendarIds);
}
else {
calDeferred.reject(resp.error);
}
});
});
return calDeferred.promise;
},
// get all events for a calendar
getEvents = function(calendarId) {
var events = [],
eventsDeferred = $q.defer();
var request = gapi.client.calendar.events.list({
calendarId: calendarId
});
request.execute(function(resp) {
if(!resp.error) {
for(var j = 0; j < resp.items.length; j++) {
events.push(resp.items[j]);
}
eventsDeferred.resolve(events);
}
else {
eventsDeferred.reject(resp.error);
}
});
return eventsDeferred.promise;
},
getAllEvents = function() {
getCalendars().then(function (calendarIds) {
var eventCalls = [];
// get promise for each calendar event query
for(var i = 0; i < calendarIds.length; i++) {
eventCalls.push(getEvents(calendarIds[i]));
}
// make all calls to get all events
$q.all(eventCalls).then(function(results) {
var aggregatedData = [];
angular.forEach(results, function (result) {
aggregatedData = aggregatedData.concat(result);
});
deferred.resolve(aggregatedData);
});
},
function (errorMessage) {
deferred.reject(errorMessage);
});
};
// login to google API before making calls
gapi.auth.authorize({
client_id: this.clientId,
scope: this.scopes,
immediate: true,
}, getAllEvents);
return deferred.promise;
}