有没有办法加速up/batchGoogle日历read/writes?

Is there a way to speed up/batch Google Calendar read/writes?

我是 Google Apps 脚本的新手,并且在进行此项目时正在学习 javascript。在介绍性代码实验室的过程中,我注意到 best practice 使用一条命令将所有数据读取到一个数组中,执行操作,然后使用一条命令将其写入。

我知道如何使用 Google 表格来完成此操作,但我如何使用 Google 日历来实现此操作?我看到了一些讨论 batching with Google Calendar API and Advanced Google Services 的链接,但我不明白如何使用这些信息。

我基本上希望批量编辑事件而不是在 for 循环中重复访问 Google 日历。

function deleteMonth() {

  //  Set Date range to delete 
  var today = new Date();
  var firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
  var lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);

  //  read spreadsheet data and get User Info from ss
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var idSheet = spreadsheet.getSheetByName('User Info');
  //Get users from sheet in array of objects with properties from column header in 
  //'User Info' (name, email, year, calName, calID, early, late)
  var userInfo = getSheetData(idSheet);
  var deletedNames = "";
  for (i = 0; i < userInfo.length; i++) {
    var calID = userInfo[i].calID;
    //    if we have calID proceed to delete events
    if (calID) {
      console.time("get events");
      var calendar = CalendarApp.getCalendarById(calID);
      var events = calendar.getEvents(firstDay, lastDay);
      console.timeEnd("get events");
      //    Delete events and add deleted name to string 
      //    deletedNames     
      for (i = 0; i < events.length; i++) {
        console.time("delete event");
        deletedNames += events[i].getTitle() + ", ";
        events[i].deleteEvent();
        console.timeEnd("delete event");
      }
    }
  }
  spreadsheet.toast("Deleted events: \n" + deletedNames);
}

console.time() 的时间输出:

其他听起来相关的相关链接:

  1. Using advanced google services(应用脚本资源)
  2. Google Developer blog?

我相信你的目标如下

  • 您想通过 Google Apps 脚本使用批处理删除多个日历一个月内的所有事件。
  • 您想降低上述过程的过程成本。

为此,这个答案怎么样?

问题和解决方法:

日历API 可以处理批处理请求。批量请求可以 运行 100 个请求通过一个 API 调用并且可以用异步进程处理。由此,我认为可以降低工艺成本。但是,不幸的是,在现阶段,多个日历 ID 不能在一批中使用。当请求包含多个日历ID时,会出现Cannot perform operations on different calendars in the same batch request.的错误。因此,在您的情况下,一个日历 ID 中一个月中的所有事件都可以在一批请求中删除。需要请求日历 ID 的数量。我想将此作为当前的解决方法。

顺便说一句,作为你scrit的修改点,在你的脚本中,变量i被用在第一个for循环和第二个for循环中。这样, userInfo 的所有值都不会被使用。请注意这一点。

示例脚本:

在你 运行 脚本之前,please enable Calendar API at Advanced Google services

function deleteMonth() {
  var today = new Date();
  var firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
  var lastDay = new Date(today.getFullYear(), today.getMonth() + 1, 0);
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var idSheet = spreadsheet.getSheetByName('User Info');
  var userInfo = getSheetData(idSheet);
  var deletedNames = "";
  var requests = []; // For batch requests.
  for (i = 0; i < userInfo.length; i++) {
    var req = [];
    var calID = userInfo[i].calID;
    if (calID) {
      var calendar = CalendarApp.getCalendarById(calID);
      var events = calendar.getEvents(firstDay, lastDay);
      for (j = 0; j < events.length; j++) {
        deletedNames += events[j].getTitle() + ", ";
        var e = events[j];
        req.push({
          method: "DELETE",
          endpoint: `https://www.googleapis.com/calendar/v3/calendars/${calID}/events/${e.getId().replace("@google.com", "")}`,
        });
      }
    }
    requests.push(req);
  }

  // Run batch requests.
  requests.forEach(req => {
    const limit = 100;
    const split = Math.ceil(req.length / limit);
    const boundary = "xxxxxxxxxx";
    for (let i = 0; i < split; i++) {
      const object = {batchPath: "batch/calendar/v3", requests: req.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};
      var res = UrlFetchApp.fetch("https://www.googleapis.com/" + object.batchPath, params);
      console.log(res.getContentText())
    }
  })

  spreadsheet.toast("Deleted events: \n" + deletedNames);
}

注:

  • 请在 V8 中使用此脚本。

参考文献: