【问题标题】:Is there a way to run two functions at the same time(simultaneously/asynchrounously) with one function as an infinite loop?有没有办法同时(同时/异步)运行两个函数,一个函数作为无限循环?
【发布时间】:2020-01-23 15:16:38
【问题描述】:

我有两个想要同时运行的函数,但我不能让它们单独运行,因为一个函数包含无限循环while(true)。而 JavaScript 的问题是,如果你在哪里运行两个函数,它会在运行下一个函数之前完成函数的运行;因此,如果我使用 while(true) 循环运行一个函数,它将永远不会移动到下一个函数。
如果你还是不明白,这是我的代码:

function onOpen(){           // Google Apps Script trigger
    infLoop()                //how to run both of these functions at the same time?
    runScript()
}

function infLoop(){          //inf loop.

    while(True){
        Utilities.sleep(100)
        DocumentApp.getActiveDocument()
        .setname("dont change this name")
    }
}

function runScript(){
    //code...
}

【问题讨论】:

标签: function asynchronous google-apps-script infinite-loop simultaneous


【解决方案1】:

Google 应用程序脚本同步执行。在大多数情况下,同时/并行处理是不可能的。根据您的脚本,您似乎希望两个函数同时运行 onOpen。可能的解决方法(一些未测试):

解决方法#1:使用不同的项目

  • 创建一个新项目:在编辑器中(仅限旧版/旧编辑器)>文件>新建>项目
  • 第一个项目的onOpen() 将运行infLoop()
  • 第二个项目的onOpen() 将运行runScript()
  • 这两个函数将在打开时同时运行。

解决方法#2:简单且可安装的触发器1

  • runScript() 创建一个可安装的触发器
  • 简单触发器onOpen() 将运行infLoop()
  • 这两个函数将在打开时同时运行。
  • 您可以使用两个可安装的触发器来代替简单且可安装的触发器。

解决方法#3:Web 应用程序:从客户端调用

  • 如果有侧边栏打开或从 Web 应用打开工作表,则可以通过 google.script.run(异步运行)重复调用服务器函数

  • Here 可以运行一个函数 6 分钟(当前运行时间)。但是通过重复调用服务端函数,可以长时间运行该函数(最多90分钟/天=当前触发器运行时配额/天)

解决方法#4:Web 应用程序:UrlFetchApp#fetchAll2

  • UrlFetchApp#fetchAll 异步运行
  • 发布 Web 应用程序后,发布的 url 可以与查询参数一起使用。如果函数名作为参数发送,doGet() 执行该函数,则.fetchAll 可以异步用于多个函数。

解决方法#5:onEdit/onChange

  • 如果进行了编辑,两个函数(onEdit/onChange)会同时运行。

解决方法#6:Sheets API/onChange

  • 如果插件/脚本通过工作表 API 进行更改,onChange可能会被触发。如果触发,通过 sheet api 进行的每项更改都会导致 onChange 异步运行。

【讨论】:

  • 谢谢!!!这有很大帮助!我明白你为什么是“大师”了。虽然有没有办法在避免脚本超时的同时进行无限循环?
  • @Mr.pizza 配额将适用。有人谈到使用 v8 将配额延长到 30 分钟。但它目前处于 alpha 阶段。它可能会在今年年底到来。在那之前,我看不到希望。一种方法是每 6 分钟对触发器进行一次计时。即使这样,您也被限制为每天 90 分钟的总配额。
  • 关于解决方法 4,您可以将 @Tanaike 的优秀库与 webapps 一起使用,但也可以不使用!选项是“使用 Web 应用程序进行并行处理”或“使用 Google Apps Script API 的 scripts.run 方法进行并行处理”。 github.com/tanaikech/RunAll
  • @TheMaster 我知道,我也希望如此。到目前为止我发现:“Gasthreader 是一个已发布的 Apps Script webapp”[1],它使用 google.script.run 来调用它 [2]。它似乎与 Workaround #3 的不同之处仅在于您只需调用 Web 应用程序/服务器一次,它将完成将作业拆分为异步并行执行并将结果合并回来的工作。 [1] sites.google.com/a/mcpher.com/share/Home/excelquirks/… [2] github.com/brucemcpherson/gasThreader/blob/…
【解决方案2】:

要“同时”运行两个或多个函数,您应该分别调用每个函数。一种方法是从客户端代码use promises

请记住,您的服务器端无限循环最终会导致您的脚本超过最大执行时间(6 分钟/30 分钟,具体取决于有效用户使用的帐户类型)。

相关

【讨论】:

    【解决方案3】:

    在 Apps 脚本中运行无限循环是徒劳的,因为有 an enforced maximum execution time of 6 minutes for most scripts。当您达到该限制时,脚本执行将被终止。

    从您的示例脚本来看,您尝试执行的是设置文档名称的计划作业。 为此,您最好使用a time-driven trigger

    然后您可以像这样构建您的脚本:

    function onOpen() {
        // code...
    }
    
    function updateDocumentName() {
        DocumentApp.getActiveDocument().setName("dont change this name")
    }
    
    

    然后,您可以将setup a time-driven trigger 关联到updateDocumentName() 函数。

    需要注意的一个主要区别:不是每 100 毫秒执行一次逻辑,您可以使用时间驱动触发器设置的最高频率是每 1 分钟一次。

    【讨论】:

      【解决方案4】:

      是的!只需将一个函数放在另一个函数中。

      function EmailSummary() {
        // Modified from http://stackoverflow.com/a/22200230/1027723 .. SOURCE: https://mashe.hawksey.info/2015/07/tips-on-emailing-inline-google-charts-from-sheets-using-apps-script/
        function emailCharts(sheet_name){    // eg "SF_EMAIL"
          sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheet_name)
          var charts = sheet.getCharts();
      
          if(charts.length==0){
            MailApp.sendEmail({
      
      ...
      

      只要确保正确缩进即可。

      【讨论】:

        猜你喜欢
        • 2023-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-26
        • 1970-01-01
        • 2015-09-19
        相关资源
        最近更新 更多