performance - 如何减少此 Google Apps 脚本的执行时间?

我写了一个脚本,从电子表格中获取行数据并循环遍历它们,如果行数据满足特定条件(例如,有电话号码但尚未发送),则调用函数发送 SMS。

但是在添加大约 600 行之后,脚本执行时间超过了它的限制,根据我的研究,这似乎是 5 分钟。我正在使用 JavaScript 对象读取数据,并使用 for 循环遍历行。

如果有可能让它更快,谁能告诉我?我对编程很陌生,但对于所有这些计算能力来说,这似乎是一项轻松的任务,我不明白为什么要花这么长时间

提前致谢!

这是我正在使用的函数的代码:

// Will send SMS on the currently active sheet
function sendSms() {

  // Use the send sms menu to trigger reconcile
  var user = ScriptProperties.getProperty(PROPERTY_USER_RECONCILE);
  if (user == null)
    reconcileUser();

  // The sheets
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Registo");
  var settingsSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Settings");

  // Fetch values for each row in the Range.
  var startRow = 2;
  var apiKey = settingsSheet.getRange("B2").getValue();
  var apiSecret = settingsSheet.getRange("B3").getValue();
  var prefix = settingsSheet.getRange("B4").getValue();
  var numRows = sheet.getMaxRows() - 1;
  var numCols = 16;
  var statusColNum = 15;  // IMPT: To keep track status in col 15
  var dataRange = sheet.getRange(startRow, 1, numRows, numCols);

  // Make sure there is API key and secret
  if (apiKey == "" || apiSecret == "") {
    Browser.msgBox("You MUST fill in your API key and secret in Settings sheet first!");
    return;
  }

  // Create one JavaScript object per row of data.
  var objects = getRowsData(sheet, dataRange);

  var totalSent = 0;

  for (var i = 0; i < objects.length; ++i) {
    // Get a row object
    var rowData = objects[i];
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    var templateSheet = ss.getSheetByName("SMS Modelo");
    var template = templateSheet.getRange("A1").getValue();

    // jump loop iteration if conditions not satisied
    if (rowData.resolv == "x" || rowData.contactoUtente == null || rowData.contactoUtente == "" || rowData.reserv == null || rowData.reserv == "" || rowData.cont == "x" || rowData.sms !== null) continue;
      var message = fillInTemplateFromObject(template, rowData);
      var senderName = "Farm Cunha"
      var mobile = rowData.contactoUtente;
      // Send via Nexmo API
      var response = nexmoSendSms(apiKey, apiSecret,"+351" + mobile, message, senderName);
      if (response.getResponseCode() == 200) {
        var object = JSON.parse(response.getContentText());
        if (object.messages[0]['status'] == "0") {
          // Set to QUEUE status - We assumed SENT, as we don't handle delivery status.
          //sheet.getRange(startRow + i, statusColNum).setValue(STATUS_QUEUE);
          sheet.getRange(startRow + i, statusColNum).setValue(STATUS_SENT);
          // Set the reference id
          sheet.getRange(startRow + i, 19).setValue(object.messages[0]['message-id']);
          // sheet.getRange(startRow + i, statusColNum+3).setValue(new Date()); linha pode ser activada para fazer timestamp do envio
          totalSent++;
          }
        else {
          // If status is not 0, then it is an error.
          // Set status to the error text
          sheet.getRange(startRow + i, statusColNum).setValue(object.messages[0]['error-text']);
        }
      }
      else {
        // Non 200 OK response
        sheet.getRange(startRow + i, statusColNum).setValue("Error Response Code: " + response.getResponseCode);
      }
      SpreadsheetApp.flush();
      // Need a wait. Need to throttle else will have "Route Busy" error.
      Utilities.sleep(2000);
  }

  // Update total sent
  var lastTotalSent = parseInt(ScriptProperties.getProperty(PROPERTY_SMS_SENT_FOR_RECONCILE));
  if (isNaN(lastTotalSent)) lastTotalSent = 0;
  ScriptProperties.setProperty(PROPERTY_SMS_SENT_FOR_RECONCILE, (lastTotalSent + totalSent).toString());
  Logger.log("Last sent: " + lastTotalSent + "  now sent: " + totalSent);
  reconcileApp();
}

最佳答案

您的循环中有一些太耗时的事情:电子表格读数和 API 调用 + 2 秒 sleep !

我显然会建议您将这些从循环中取出(特别是始终相同的模板表阅读!)。一种可能的解决方案是检查行对象的条件并将有效条目保存在数组中……然后在该数组中迭代以调用 API。

如果这仍然太长,则小批量进行,将部分迭代的结束位置保存在 scriptproperties 中,并使用计时器触发器,该触发器将每 5 分钟继续该过程,直到完成(并在结束时终止触发器).

这个论坛上有一些这种“机制”的例子,我最近推荐的一个例子是 here (它更像是一个草稿,但想法是存在的)

https://stackoverflow.com/questions/15303762/

相关文章:

sql - 从当前 sysdate 中检索最近两年的数据

vbscript - SystemUtil.Run 在 vb 脚本中不起作用

string - 一组字符串的 R 直方图和描述性统计数据

.net - 将 OrderedDictionary 转换为 Dictionary

java - 如何在其他计算机上运行java可执行文件

c# - 在 XSL 中创建空格 ( )

solr - 从 DocsAndPositionsEnum 检索所有术语位置

unix - 输出 shell 脚本到日志文件

django - 如何为多个 View 设置 cookie?

php - 在 TYPO3 Fluid 中显示按年和按月分组的元素列表