按顺序运行多个脚本

时间:2019-11-07 19:44:32

标签: google-apps-script

我的项目中有以下脚本的5个版本,这些版本可以从Google Analytics(分析)提取(每个提取一组页面)。我目前必须手动运行每个程序,并希望它们依次运行。我已经通过这种方式进行设置,以绕过6分钟的时间限制。

是否有一种方法可以运行第一个脚本,完成后是否有脚本化的触发器指向下一个要自动运行的脚本?

function main3() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  for (var i = 1; i < 32; i++) {      
    var istring = i.toString();
    var sheetName = istring;
    var istring1 = "a" + ((i+1).toString());
    var sheet = spreadsheet.getSheetByName(sheetName);
    //sheet.clearContents();  
  }
  for (var j = 27; j < 40; j++) {
    var jstring = j.toString();
    var jstring1 = "d" + ((j+1).toString());
    var ss = SpreadsheetApp.openById("..."); 
    var sheet2 = ss.getSheetByName('GA ID & SS KEY');
    var sheet1 = ss.getSheetByName('Dates');
    var allRows = sheet1.getRange(2, 1, 31).getValues();  
    var timeZone = ss.getSpreadsheetTimeZone();
    var tableId = sheet2.getRange(jstring1).getValue();
    //var lastRow = 2;           
    for (var i = 1; i < 32; i++) {    
      var istring = i.toString();
      var sheetName = istring;
      var istring1 = "a" + ((i+1).toString());
      var sheet = spreadsheet.getSheetByName(sheetName);
      var startDate1 = Utilities.formatDate(allRows[i-1][0], timeZone, "YYYY-MM-dd");
      var endDate1 =  startDate1;
      var lastRow = sheet.getLastRow();
      if (lastRow == 0) {
        lastRow = 2;
      } else {
        lastRow = lastRow + 1;
      }
      var metrics = ['ga:pageviews,ga:uniquePageviews,ga:users,ga:newUsers,ga:entrances'];
      var options = {
        'dimensions': 'ga:hostname,ga:pagePath,ga:dimension3,ga:date',
        'filters': 'ga:dimension3==commerce',
        'sort': '-ga:pageviews',
        //'segment': '',
        'samplingLevel': 'HIGHER_PRECISION',
        'max-results': '10000'
      }      
      var report = gaGet(tableId, startDate1, endDate1, metrics, options);
      if (report.rows !== undefined) {    
        Logger.log(report.rows.length);
        var data = report.rows;
        var writeRange = sheet.getRange(lastRow, 1, data.length, data[0].length) 
        writeRange.setValues(data);
      }
    }
  }
}

function gaGet3(tableId, startDate1, endDate1, metrics, options) {
  // Apply standard options
  options = options || {};
  options['max-results'] = options['max-results'] || '10000';  
  for (var i = 0; i < 5; i++) {
    try {
      return Analytics.Data.Ga.get(tableId, startDate1, endDate1, metrics, options); 
    } catch (err) {      
      if (err.message.indexOf('a server error occurred') > -1) {
        Logger.log('Backend Error');        
        Utilities.sleep(2 * 60 * 1000);
      } else if (err.message.indexOf('User Rate') > -1) {
        Logger.log('Rate Limit Error');        
        Utilities.sleep(1000 * Math.pow((i + 1), 2));
      } else if (err.message.indexOf('too many concurrent connections') > -1) {
        Logger.log('Concurrent Connections Error');        
        Utilities.sleep(1000 * Math.pow((i + 1), 2));
      } else {
        Logger.log(err);
        throw err;
      }
    }
  }
  throw 'Error. Max retries reached';
}

2 个答案:

答案 0 :(得分:0)

我查看了您的代码,我认为您可以简化很多代码。例如,代码中的第一个循环不执行任何操作,因此您可以将其删除。此外,经验丰富的程序员将使代码受益。它可能是大小的三分之一。但是,真正的问题是,看起来好像您从Analytics.data.ga调用报告,您可能无法控制它,并且基于第二个函数的外观,您调用它的速度太快了。因此,我倾向于将其用5分钟的计时器运行,并将从1到31的索引存储在PropertiesService中,并在深夜进行,并让您的报告在早上等待您。如果这些报告对您很重要,建议您雇用某人来帮助您。

答案 1 :(得分:0)

我认为绕过6分钟时间限制的最佳方法是在每个函数的末尾创建一个基于时间的触发器,该触发器将在指定的时间后调用以下函数。

此处要注意的方法是after(durationMilliseconds)。因此,您可以在指定的毫秒数后运行指定的任何功能。

例如,如果我们有三个函数,如果一个接一个地运行它们,则需要花费6分钟以上的时间才能完成,那么您可以在以下几行中做一些事情:

function myFunction1() {
  // Whatever myFunction1 does
  ScriptApp.newTrigger("myFunction2")
  .timeBased()
  .after(1000) // This fires the second function 1 second after the first one ends. Change this time according to your preferences
  .create();
}

function myFunction2() {
  // Whatever myFunction2 does
  ScriptApp.newTrigger("myFunction3")
  .timeBased()
  .after(1000) // This fires the third function 1 second after the second one ends. Change this time according to your preferences
  .create();
}

function myFunction3() {
  // Whatever myFunction3 does
}

另一种方法是使用Apps Script API远程run的不同功能,但这是一个较难的解决方法。

不选择使用libraries,因为与库相对应的执行时间算作调用这些库的原始脚本的一部分。

当然,在使用触发器之前,要做的第一件事就是提高代码的效率,以使运行时间少于6分钟。

我希望这会有所帮助。