My code for an API pull has been timing out a lot lately. Here is my code (note that I have changed some variables for privacy):
// SHEET DATA
var ss = SpreadsheetApp.getActive();
var data_sheet = ss.getSheetByName('data');
var view_sheet = ss.getSheetByName('views');
var num_rows = view_sheet.getDataRange().getNumRows()
// API URL
var api_url = "url"
var api_url2 = "end of url"
// AUTH
var user = 'email'
var apikey = "apikey"
var token = user + "/token:" + apikey;
var encode = Utilities.base64Encode(token);
var params =
{
"method" : "get",
"headers" :
{
"Content-type":"application/xml",
"Authorization": "Basic " + encode
}
};
// calls the zendesk API for each view on the views tab, adds it's view count as a new row on the data sheet
function zdAPIcall() {
// for date formatting
var time = new Date();
var time_utc = new Date(time.getUTCFullYear(), time.getUTCMonth(), time.getUTCDate(), time.getUTCHours(), time.getUTCMinutes(), time.getUTCSeconds());
// loops through views on views tab (excluding header row)
for (i=2; i<=num_rows; i++) {
// pulls the view ID
var view_id = view_sheet.getRange(i, 1).getValue();
// builds the API URL
var full_api = api_url + view_id + api_url2;
// finds the last row to add the value to
var update_row = data_sheet.getLastRow() + 1;
// hits the zendesk api
var response = UrlFetchApp.fetch(full_api,
params);
// pulls the response as json, extracts the view count value
var json = response.getContentText();
var data = JSON.parse(json);
var view_count = data['view_count']['value']
// adds the data as a new row to the data sheet
data_sheet.getRange(update_row,1).setValue(time_utc)
data_sheet.getRange(update_row,2).setValue(view_id)
data_sheet.getRange(update_row,3).setValue(view_count)
Logger.log("row added!")
};
};
Best Answer
It's better not to call
setValue
in a loop, but instead form a double array of values to be inserted, and put them all at once withsetValues
. This often helps with keeping resource use under quota.However, in your case the main issue is not
setValue
butUrlFetchApp.fetch
in a loop. Hitting some API a bunch of times in a loop is an expensive thing to do, both for your script and the API provider. The maximum execution time of Apps Script is 6 minutes, after which the script is terminated with the message you quoted. To avoid this, follow Anton Soradoi's advice:Terminating a script means recording the starting time
start = Date.now()
, and then checking in the loop whether you are running over 5 minutes (start+5*60*1000
). If this happens, exit the loop (hence the script) but set a trigger to resume work in a few minutes. Since you already work with a spreadsheet and record the results there, it will not be difficult to find the place where the script should pick up the work after restart.