performance - 有没有办法加速/批量 Google 日历读/写?

标签 performance google-apps-script google-calendar-api

我是 Google Apps 脚本新手,在开展此项目时正在学习 javascript。在介绍性代码实验室的过程中,我注意到 best practice一条命令将所有数据读入数组,进行运算,然后一条命令写入。

我了解如何使用 Google 表格实现此目的,但如何使用 Google 日历实现此目的?我遇到了一些讨论batching with Google Calendar API的链接和 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() 的时间输出:

Time output from console.time()

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

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

最佳答案

我相信你的目标如下

  • 您想要使用 Google Apps 脚本进行批处理,删除多个日历一个月内的所有事件。
  • 您希望降低上述流程的流程成本。

对于这个,这个答案怎么样?

问题和解决方法:

日历API可以处理批量请求。批量请求可以通过一次 API 调用运行 100 个请求,并且可以使用异步流程进行处理。这样,我认为可以降低工艺成本。但是,遗憾的是,在现阶段,多个日历ID不能批量使用。当请求中包含多个日历ID时,会出现无法在同一批处理请求中对不同日历执行操作。的错误。因此,在您的情况下,可以在一批请求中删除一个日历 ID 中一个月内的所有事件。需要请求日历ID的数量。我想建议将此作为当前的解决方法。

顺便说一句,作为脚本的修改点,在脚本中,变量 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 一起使用。

引用文献:

关于performance - 有没有办法加速/批量 Google 日历读/写?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62205086/

相关文章:

sql - 计算所有 child 都属于特定类型的 parent 类型

javascript - 将 GCSQL 中存储为 blob 的 SVG 图像转换为 Apps 脚本中的字符串

javascript - 如何验证dialogflow中的参数输入

html - 使用 Html 服务引用项目文件

google-calendar-api - Google Apps日历显示 “Busy”而不是共享完整的详细信息

google-api - 为什么我没有收到已删除或修改其实例之一的重复事件的 EXDATE?

arrays - Postgresql - 在大数据库中使用数组的性能

c++ - Windows 和 OSX 之间 iostream 控制台输出的性能差异?

过滤器中带有大(?)IN 列表的 Postgresql 10 查询

google-apps-script - 如何将具有多行的 2 列单元格拆分为唯一的行,同时保留/复制周围的数据?