我正在使用谷歌提供的应用程序脚本,通过表格访问他们的预测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);
}
}
为什么你的代码没有按预期运行:
1)既然你提到,"我在当前触发器列表中看到它,但它永远不会再次被调用",看看你的代码,我不确定你是否打算在它的执行完成后再次调用该函数。如果您这样做,这是因为您的for
循环运行了一段时间,直到获得instances
的长度。脚本中没有任何内容表明该函数在完成对instances
的迭代后需要再次运行。请参阅此链接,了解如何以编程方式管理触发器。
var builder = ScriptApp.newTrigger('predict').timeBased().after(REASONABLE_TIME_TO_WAIT);
这行代码属于if
条件,停止执行1分钟(值为60000)。因此,在执行开始后的时间上增加1分钟。您没有将startTime
计数器重置为等待时间之后的时间,因为一旦currTime - startTime
的值超过MAX_RUNNING_TIME
,该函数将在此后的for
循环的所有迭代中继续调用if
循环。简单地说,如果startTime
是9:35,currTime
是9:40,等待1分钟后,currTime
是9:41,仍然比MAX_RUNNING_TIME
(5分钟)多,因为startTime
的值仍然是9:35。此时将其重置为9:41应该可以解决您的问题。
3)在if
循环中丢失break
可能也有助于解决这个问题。
添加一个函数,如下面的链接所示:
function callTrigger(){
ScriptApp.newTrigger('predict')
.timeBased()
.everyMinutes(30)
.create();
}
在编辑器中运行一次callTrigger函数,应该就可以了。请记住,对于几分钟,您只能传递值1、5、15或30。