1

我正在使用 Google 提供的应用脚本通过工作表访问他们的预测 API。我试图一次预测数千行,但是,在 6 分钟后,代码停止时达到了最大执行时间。

我实现了一个使用时钟触发器构建器找到的解决方案。一旦我运行该功能,它会持续 5 分钟,然后它会停止设置触发器以在 2 分钟内调用该功能。

主要问题是函数在调度时没有被调用。我在当前的触发器列表中看到它,但它再也不会被调用。您能否解释一下为什么会发生这种情况。

我的意图是在 5 分钟内预测尽可能多的行,然后停止设置触发器以在几分钟内再次调用预测函数,从它停止的地方开始并继续,直到预测到任何元素。

我还需要知道如何将值存储在缓存中,以便在再次调用函数时知道它需要的所有信息。

//This is the function that is used to predict a selection of data
function predict() {
  try {
    clearOutput();
    var startTime= (new Date()).getTime();
    var sheet = SpreadsheetApp.getActiveSheet();
    var selection = sheet.getActiveSelection();
    var instances = selection.getValues();
    var project_number = getProjectNumber();
    var model_name = getModelName();
    var startRow = stRow; 
    var MAX_RUNNING_TIME = 300000;
    var REASONABLE_TIME_TO_WAIT = 60000;
    for (var i = startRow; i < instances.length; ++i) {
      var currTime = (new Date()).getTime();
      if(currTime - startTime >= MAX_RUNNING_TIME) {
        var builder = ScriptApp.newTrigger('predict').timeBased().after(REASONABLE_TIME_TO_WAIT);
    builder.create();
    break;
  } else {  
    var result = predictSingleRow(project_number, model_name, instances[i]);
    selection.getCell(i + 1, 1).setValue(result);
  }
    }
  } catch(e) {
    Browser.msgBox('ERROR:' + e, Browser.Buttons.OK);
  }
}
4

1 回答 1

0

关于为什么您的代码没有按预期运行的几件事:

1)既然您提到“我在当前触发器列表中看到它,但它再也不会被调用”并查看您的代码,我不确定您是否打算在执行完成后再次调用该函数。如果这样做,这是因为您的for循环会运行一段时间,直到获得 的长度instances。脚本中没有任何内容表明该函数在完成迭代后需要再次运行instances。请参阅此链接以了解如何以编程方式管理触发器

2)var builder = ScriptApp.newTrigger('predict').timeBased().after(REASONABLE_TIME_TO_WAIT);

您的这行代码处于if停止执行 1 分钟(值为 60000)的条件下。因此,自执行开始以来的时间增加 1 分钟。因为一旦 的值已经超过,您将无处将startTime计数器重置为等待时间之后的时间,此后该函数将继续为循环的所有迭代调用循环。简单地说,如果是 9:35 和9:40,在等待 1 分钟后是 9:41,这仍然比(5 分钟)多,因为值仍然是 9:35。此时将其重置为 9:41 应该可以解决您的问题。currTime - startTimeMAX_RUNNING_TIMEifforstartTimecurrTimecurrTimeMAX_RUNNING_TIMEstartTime

3)失去循环可能也有助于解决这个问题breakif

编辑:

添加一个函数,如我上面提到的链接所示:

function callTrigger(){
  ScriptApp.newTrigger('predict')
      .timeBased()
      .everyMinutes(30)
      .create();
}

从您的编辑器运行一次函数 callTrigger ,您应该一切顺利。请记住,对于分钟,您只能传递值 1、5、15 或 30。

于 2015-08-03T18:17:20.527 回答