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:
- Get all calendars, and return a promise
- After call to get all calendars completes, create a promise for each event query needed
- use Angular's
$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;
}