Google Apps 脚本日历服务:分块处理许多事件:如何以编程方式触发下一个函数 运行 继续下一个块?
Google Apps Script Calendar Service: Process many events in chunks: How to programmatically trigger next function run to continue with next chunk?
我指的是 。
function renameEvents() {
var cal = CalendarApp.getCalendarById("Calendar Id");
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
var sp = PropertiesService.getScriptProperties();
if (!(sp.getProperty("count")) || sp.getProperty("count") == 0) {
var count = 0;
else if ((sp.getProperty("count") > 0) {
var count = sp.getProperty("count");
}
for (var i = count; i < events.length; i++) {
events[i].setTitle(events[i].getTitle() + " something");
events[i].setDescription(events[i].getDescription() + " something else");
sp.setProperty("count", i)
}
}
初始函数运行是时间触发的。如何以编程方式触发下一个函数 运行 继续下一个块?
我相信你的目标如下。
您想降低以下脚本的处理成本。该脚本来自您问题中的 the URL。
var cal = CalendarApp.getCalendarById("Calendar Id");
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
for (var i = 0; i < events.length; i++) {
events[i].setTitle(events[i].getTitle() + " something");
events[i].setDescription(events[i].getDescription() + " something else");
}
您想修改Google日历中所有活动的活动标题和活动描述。
问题和解决方法:
- 在您当前的脚本中,所有事件的标题和事件描述都尝试在for循环中修改。在您当前的脚本中,循环是 运行 直到发生错误。当错误发生时,使用 time-driven 触发器从
count
开始循环。我是这样理解的。
- 在你上面的脚本中,当事件数量很大时,最大执行时间已经结束。因为我觉得
setTitle
和setDescription
成本高
- 在您当前的脚本中,除了
setTitle
和setDescription
之外,for循环中还使用了setProperty
。这样的话,工艺成本会更高。
在我的回答中,作为一种解决方法,我建议针对您的情况使用 the batch request。日历 API 可以被批量请求 运行。批量请求是运行异步处理,一次API调用可以运行100个请求。由此,可以降低工艺成本。所以我想当批量请求用于你的情况时,你的所有任务可能可以通过一个 运行ning 脚本来实现。
用法:
1。安装 Google Apps 脚本库。
为了使用此示例脚本,请安装 BatchRequest. You can see the method for installing the library at https://github.com/tanaikech/BatchRequest#how-to-install 的 Google Apps 脚本库。
2。 运行 示例脚本。
请复制并粘贴以下脚本。并且 please enable Google Calendar API at Advanced Google services。并且请将您的日历 ID 设置为 calendarId
.
function myFunction() {
const calendarId = "###";
var cal = CalendarApp.getCalendarById(calendarId);
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
// Create requests for the batch request.
const reqs = events.map(e => ({
method: "PUT",
endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${e.getId().replace("@google.com", "")}`,
requestBody: {
start: {dateTime: e.getStartTime().toISOString()},
end: {dateTime: e.getEndTime().toISOString()},
summary: e.getTitle() + " something",
description: e.getDescription() + " something else"
}
}));
// Run batch requests.
const limit = 100;
const split = Math.ceil(reqs.length / limit);
for (let i = 0; i < split; i++) {
BatchRequest.Do({batchPath: "batch/calendar/v3", requests: reqs.splice(0, limit)});
}
}
- 当你运行
myFunction
的功能时,所有事件的标题和描述都通过Events:update in CalendarAPI的方法修改。
注:
- 此脚本修改所有事件的标题和描述。所以请注意这一点。所以一开始,作为测试运行,我想测试小事件数
- 在我的环境中,当我针对 100 个事件测试上述脚本时,处理时间约为 7 秒。我不确定你的总事件数。
- 在这个回答中,我建议使用Events:update的方法,而不是Events:patch的方法。因为在使用Events: patch的时候,我确认只修改了requested all events的一部分。我认为这可能是一个错误。所以我用了"Events: update"的方法。在这种情况下,我可以确认所有事件都已修改。
- 请在 V8 中使用此脚本。
参考文献:
已添加:
在此示例脚本中,没有使用 GAS 库。
示例脚本:
function myFunction() {
const calendarId = "###";
var cal = CalendarApp.getCalendarById(calendarId);
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
// Create requests for the batch request.
const reqs = events.map(e => ({
method: "PUT",
endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${e.getId().replace("@google.com", "")}`,
requestBody: {
start: {dateTime: e.getStartTime().toISOString()},
end: {dateTime: e.getEndTime().toISOString()},
summary: e.getTitle() + " something",
description: e.getDescription() + " something else"
}
}));
// Run batch requests.
const limit = 100;
const split = Math.ceil(reqs.length / limit);
const boundary = "xxxxxxxxxx";
for (let i = 0; i < split; i++) {
const object = {batchPath: "batch/calendar/v3", requests: reqs.splice(0, limit)};
const payload = object.requests.reduce((s, e, i) => s += "Content-Type: application/http\r\nContent-ID: " + i + "\r\n\r\n" + e.method + " " + e.endpoint + "\r\nContent-Type: application/json; charset=utf-8\r\n\r\n" + JSON.stringify(e.requestBody) + "\r\n--" + boundary + "\r\n", "--" + boundary + "\r\n");
const params = {method: "post", contentType: "multipart/mixed; boundary=" + boundary, payload: payload, headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}, muteHttpExceptions: true};
UrlFetchApp.fetch("https://www.googleapis.com/" + object.batchPath, params);
}
}
已添加:
- 您想在不使用日历的情况下实现上述目标 API。
为此,这个修改怎么样?
修改点:
在您的脚本中,以下部分存在语法错误。
if (!(sp.getProperty("count")) || sp.getProperty("count") == 0) {
var count = 0;
else if ((sp.getProperty("count") > 0) {
var count = sp.getProperty("count");
}
- 请将
else if ((sp.getProperty("count") > 0) {
修改为} else if (sp.getProperty("count") > 0) {
。
getProperty
获取的值是字符串类型。从 your replying 中的 nothing happes
,我认为这可能是您问题的原因。
那么下面的修改呢?
修改后的脚本:
从:
if (!(sp.getProperty("count")) || sp.getProperty("count") == 0) {
var count = 0;
else if ((sp.getProperty("count") > 0) {
var count = sp.getProperty("count");
}
到:
var count = Number(sp.getProperty("count")) || 0;
参考:
我指的是
function renameEvents() {
var cal = CalendarApp.getCalendarById("Calendar Id");
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
var sp = PropertiesService.getScriptProperties();
if (!(sp.getProperty("count")) || sp.getProperty("count") == 0) {
var count = 0;
else if ((sp.getProperty("count") > 0) {
var count = sp.getProperty("count");
}
for (var i = count; i < events.length; i++) {
events[i].setTitle(events[i].getTitle() + " something");
events[i].setDescription(events[i].getDescription() + " something else");
sp.setProperty("count", i)
}
}
初始函数运行是时间触发的。如何以编程方式触发下一个函数 运行 继续下一个块?
我相信你的目标如下。
您想降低以下脚本的处理成本。该脚本来自您问题中的 the URL。
var cal = CalendarApp.getCalendarById("Calendar Id"); var startTime = new Date(1850, 0, 1); var endTime = new Date(2100, 0, 1); var events = cal.getEvents(startTime, endTime); for (var i = 0; i < events.length; i++) { events[i].setTitle(events[i].getTitle() + " something"); events[i].setDescription(events[i].getDescription() + " something else"); }
您想修改Google日历中所有活动的活动标题和活动描述。
问题和解决方法:
- 在您当前的脚本中,所有事件的标题和事件描述都尝试在for循环中修改。在您当前的脚本中,循环是 运行 直到发生错误。当错误发生时,使用 time-driven 触发器从
count
开始循环。我是这样理解的。 - 在你上面的脚本中,当事件数量很大时,最大执行时间已经结束。因为我觉得
setTitle
和setDescription
成本高 - 在您当前的脚本中,除了
setTitle
和setDescription
之外,for循环中还使用了setProperty
。这样的话,工艺成本会更高。
在我的回答中,作为一种解决方法,我建议针对您的情况使用 the batch request。日历 API 可以被批量请求 运行。批量请求是运行异步处理,一次API调用可以运行100个请求。由此,可以降低工艺成本。所以我想当批量请求用于你的情况时,你的所有任务可能可以通过一个 运行ning 脚本来实现。
用法:
1。安装 Google Apps 脚本库。
为了使用此示例脚本,请安装 BatchRequest. You can see the method for installing the library at https://github.com/tanaikech/BatchRequest#how-to-install 的 Google Apps 脚本库。
2。 运行 示例脚本。
请复制并粘贴以下脚本。并且 please enable Google Calendar API at Advanced Google services。并且请将您的日历 ID 设置为 calendarId
.
function myFunction() {
const calendarId = "###";
var cal = CalendarApp.getCalendarById(calendarId);
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
// Create requests for the batch request.
const reqs = events.map(e => ({
method: "PUT",
endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${e.getId().replace("@google.com", "")}`,
requestBody: {
start: {dateTime: e.getStartTime().toISOString()},
end: {dateTime: e.getEndTime().toISOString()},
summary: e.getTitle() + " something",
description: e.getDescription() + " something else"
}
}));
// Run batch requests.
const limit = 100;
const split = Math.ceil(reqs.length / limit);
for (let i = 0; i < split; i++) {
BatchRequest.Do({batchPath: "batch/calendar/v3", requests: reqs.splice(0, limit)});
}
}
- 当你运行
myFunction
的功能时,所有事件的标题和描述都通过Events:update in CalendarAPI的方法修改。
注:
- 此脚本修改所有事件的标题和描述。所以请注意这一点。所以一开始,作为测试运行,我想测试小事件数
- 在我的环境中,当我针对 100 个事件测试上述脚本时,处理时间约为 7 秒。我不确定你的总事件数。
- 在这个回答中,我建议使用Events:update的方法,而不是Events:patch的方法。因为在使用Events: patch的时候,我确认只修改了requested all events的一部分。我认为这可能是一个错误。所以我用了"Events: update"的方法。在这种情况下,我可以确认所有事件都已修改。
- 请在 V8 中使用此脚本。
参考文献:
已添加:
在此示例脚本中,没有使用 GAS 库。
示例脚本:
function myFunction() {
const calendarId = "###";
var cal = CalendarApp.getCalendarById(calendarId);
var startTime = new Date(1850, 0, 1);
var endTime = new Date(2100, 0, 1);
var events = cal.getEvents(startTime, endTime);
// Create requests for the batch request.
const reqs = events.map(e => ({
method: "PUT",
endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${e.getId().replace("@google.com", "")}`,
requestBody: {
start: {dateTime: e.getStartTime().toISOString()},
end: {dateTime: e.getEndTime().toISOString()},
summary: e.getTitle() + " something",
description: e.getDescription() + " something else"
}
}));
// Run batch requests.
const limit = 100;
const split = Math.ceil(reqs.length / limit);
const boundary = "xxxxxxxxxx";
for (let i = 0; i < split; i++) {
const object = {batchPath: "batch/calendar/v3", requests: reqs.splice(0, limit)};
const payload = object.requests.reduce((s, e, i) => s += "Content-Type: application/http\r\nContent-ID: " + i + "\r\n\r\n" + e.method + " " + e.endpoint + "\r\nContent-Type: application/json; charset=utf-8\r\n\r\n" + JSON.stringify(e.requestBody) + "\r\n--" + boundary + "\r\n", "--" + boundary + "\r\n");
const params = {method: "post", contentType: "multipart/mixed; boundary=" + boundary, payload: payload, headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}, muteHttpExceptions: true};
UrlFetchApp.fetch("https://www.googleapis.com/" + object.batchPath, params);
}
}
已添加:
- 您想在不使用日历的情况下实现上述目标 API。
为此,这个修改怎么样?
修改点:
在您的脚本中,以下部分存在语法错误。
if (!(sp.getProperty("count")) || sp.getProperty("count") == 0) { var count = 0; else if ((sp.getProperty("count") > 0) { var count = sp.getProperty("count"); }
- 请将
else if ((sp.getProperty("count") > 0) {
修改为} else if (sp.getProperty("count") > 0) {
。
- 请将
getProperty
获取的值是字符串类型。从 your replying 中的nothing happes
,我认为这可能是您问题的原因。
那么下面的修改呢?
修改后的脚本:
从:if (!(sp.getProperty("count")) || sp.getProperty("count") == 0) {
var count = 0;
else if ((sp.getProperty("count") > 0) {
var count = sp.getProperty("count");
}
到:
var count = Number(sp.getProperty("count")) || 0;