google-apps-script - 是否可以在 Apps Script 中获取新的 Google 幻灯片演示数据?

标签 google-apps-script concurrency locking simultaneous google-slides

似乎如果使用 SlidesApp.getActivePresentation()在 AppsScript 中,函数的结果不是新鲜的,而是事先准备好的东西。

场景

假设您有两个用户同时在 AppsScript 中执行以下功能:

function updateSlideText(slideId) {
  // Request exclusive write access to the document
  var lock = LockService.getDocumentLock();
  lock.waitLock(15000);

  // Perform changes
  var presentation = SlidesApp.getActivePresentation();
  var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
  textBox.asShape().getText().setText('My text');

  // Save and release lock
  presentation.saveAndClose();
  lock.releaseLock();
}

如果同时调用此函数两次,则生成的幻灯片将包含文本“My textMy text”。 Example outpu

当我添加 Utilities.sleep(10000)就在锁释放之前,它将第二次执行延迟了 10 秒,但在这 10 秒之后,我仍然得到相同的结果。另一方面,如果我真的延迟 调用 函数10s,输出正常。

由此我得出结论,我是否调用 saveAndClose 并不重要。并使用锁。一旦调用该函数,它将始终具有陈旧数据。有没有解决的办法?获取锁后是否不能请求加载新数据?

更多详情

一些更多的伪代码可以更好地说明问题用例:
// The addon frontend
websocket.onMessage((message) => {
  if (message.type === 'pollUpdate') {
    const slideWithPoll = store.getState().slides.find(
      slide => slide.pollId === message.pollId
    );

    if (slideWithPoll.title !== message.poll.title) {
      google.script.run.updateSlideText(slideWithPoll.id, message.poll.title);
    }
  }
});

最佳答案

我相信你的目标如下。

  • 当 2 个用户同时运行您的 Google 幻灯片脚本时,您希望单独运行脚本。

  • 为此,这个答案怎么样?

    问题和解决方法:

    当我测试你的情况时,我可以确认同样的问题,如 My textMy text .经过多次测试,在这种情况下,我认为LockService可能不会影响Google Slides。因此,作为一种解决方法,我建议使用 Web Apps 作为包装器。因为众所周知,Web Apps 可以由 LockService 独占运行。此变通方法的流程如下。
  • 运行脚本时,脚本会向 Web 应用程序发出请求。
  • 在 Web Apps 中,您的脚本正在运行。

  • 这样,即使在运行脚本时,脚本也可以与 LockService 同时运行。

    用法:

    该示例脚本的用法如下。请执行以下流程。

    1. 准备脚本。

    当你的脚本被使用时,它变成如下。请将以下脚本复制并粘贴到脚本编辑器中。请设置MY_SLIDE_IDMY_TEXTBOX_ID .
    function doGet() {
    
      // This is your script.
      var presentation = SlidesApp.getActivePresentation();
      var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
      var text = textBox.asShape().getText();
      text.setText('My text');
    
      return ContentService.createTextOutput("ok");
    }
    
    // Please run this function.
    function main() {
      var lock = LockService.getDocumentLock();
      if (lock.tryLock(10000)) {
        try {
          const url = "https://script.google.com/macros/s/###/exec";  // Please set the URL of Web Apps after you set the Web Apps.
          const res = UrlFetchApp.fetch(url);
          console.log(res.getContentText())
        } catch(e) {
          throw new Error(e);
        } finally {
          lock.releaseLock();
        }
      }
    }
    

    2. 部署 Web 应用程序。
  • 在脚本编辑器上,通过“发布”->“部署为 Web 应用程序”打开一个对话框。
  • 选择 “我” “执行应用程序为:” .
  • 通过这种方式,脚本以所有者身份运行。
  • 选择 “任何人,甚至匿名” “谁有权访问该应用程序:” .
  • 在这种情况下,不需要请求访问 token 。我认为我推荐使用此设置来测试此解决方法。
  • 当然,您也可以使用访问 token 。到时候请把这个设为 “任何人” .并请包括https://www.googleapis.com/auth/drive.readonly的范围和 https://www.googleapis.com/auth/drive到访问 token 。这些范围是访问 Web 应用程序所必需的。
  • 单击“部署”按钮作为新的“项目版本”。
  • 自动打开“需要授权”对话框。
  • 单击“查看权限”。
  • 选择自己的帐户。
  • 在“此应用程序未经验证”处单击“高级”。
  • 点击“转到###项目名称###(不安全)”
  • 单击“允许”按钮。
  • 单击“确定”。
  • 复制 Web 应用程序的 URL。就像 https://script.google.com/macros/s/###/exec .
  • 当您修改 Google Apps 脚本时,请重新部署为新版本。这样,修改后的脚本就会反射(reflect)到 Web Apps 中。请注意这一点。
  • 请设置https://script.google.com/macros/s/###/exec的网址至 url以上脚本。并请重新部署 Web 应用程序。这样,最新的脚本就会反射(reflect)到 Web Apps 中。所以请注意这一点。

  • 4. 测试此解决方法。

    请运行main()的功能由 2 个用户同时进行,正如您所测试的那样。由此,发现脚本是独占运行的。在我的环境中,在这种情况下,我确认即使没有使用 LockService,脚本也会以独占方式运行。但我想建议使用 LockService 以防万一。

    笔记:
  • 这是一个简单的示例脚本,用于解释此解决方法。所以在使用的时候请根据自己的实际情况进行修改。
  • 关于LockService可能对Google Slides没有影响的情况,现阶段,虽然不知道是不是bug,如何反馈给the Google issue tracker ?不幸的是,我在当前的 Google 问题跟踪器中找不到这个问题。

  • 引用:
  • Web Apps
  • Taking advantage of Web Apps with Google Apps Script
  • 关于google-apps-script - 是否可以在 Apps Script 中获取新的 Google 幻灯片演示数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62166790/

    相关文章:

    c# - C# 中的事务并发

    java - 在 future list 上流式传输的最有效方式

    c# - 如何检查 Windows 锁定设置?

    google-apps-script - 输出其他内容类型;除了带有 Apps 脚本的 HTML

    google-apps-script - 使用UrlFetch时抛出"Unexpected error"

    javascript - 将多个工作表名称传递到数组中 Google App 脚本不适用于时间戳函数

    java - ConcurrentHashMap 中的 Dose Segment 存在虚假共享问题?

    C#:从锁定 block 调用事件

    vb.net - 使用 SyncLock 的正确方法(一般)

    google-apps-script - 在 Google Apps 脚本中设置单元格边框宽度