首页 > 解决方案 > 谷歌文档应用程序脚本函数调用非常慢

问题描述

我正在编写一个谷歌文档应用程序脚本来制作谷歌文档插件。当用户单击侧边栏中的按钮时,应用程序脚本函数称为命名executeSpellChecking。此应用程序脚本函数在获取文档文本后进行远程 POST 调用。

total time= 从用户单击按钮到 的时间.withSuccessHandler(,这意味着直到executeSpellChecking返回 = 2000 毫秒

function time=executeSpellChecking调用从开始到结束所用的时间 = 1400 毫秒

t3 = 完成远程 POST 调用所需的时间 = 800ms

t4 = 在 VB.NET 应用程序中完成相同的远程 POST 调用所需的时间 = 200 毫秒

问题:

为什么total time to completetotal function time惊人的 600 毫秒大,那里还会发生什么?他们不应该是平等的吗?我该如何改进它?

为什么t3大于t4?他们不应该是平等的吗?从 .gs 发生的 POST 请求有问题吗?我该如何改进它?

代码是(sidebar.html):

  function runSpellChecking() {
    gb_IsSpellcheckingRunning = true;
    //gb_isAutoCorrecting = false;
    gi_CorrectionCurrWordIndex = -1;
    $("#btnStartCorr").attr("disabled", true);

    $("#divMistakes").html("");
    this.disabled = true;
    //$('#error').remove();
    var origin = $('input[name=origin]:checked').val();
    var dest = $('input[name=dest]:checked').val();
    var savePrefs = $('#save-prefs').is(':checked');
    //var t1 = new Date().getTime();
    console.time("total time");
    google.script.run
        .withSuccessHandler(
          function(textAndTranslation, element) {
            if (gb_IsSpellCheckingEnabled) {
              console.timeEnd("total time");
              //var t2 = new Date().getTime();
              go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
              var pagewords = textAndTranslation.pagewords;
              var spellchecked = textAndTranslation.spellchecked;
              //alert("total time to complete:" + (t2-t1) + "###" + go_TextAndTranslation.time);
              //irrelevant code follows below...
            }
          })
        .withFailureHandler(
          function(msg, element) {
            showError(msg, $('#button-bar'));
            element.disabled = false;
          })
        .withUserObject(this)
        .executeSpellChecking(origin, dest, savePrefs);
  }

调用的函数代码是(spellcheck.gs):

function executeSpellChecking(origin, dest, savePrefs) {
  //var t1 = new Date().getTime();
  console.time("function time");
  var body = DocumentApp.getActiveDocument().getBody();
  var alltext = body.getText();
  var lastchar = alltext.slice(-1);
  if (lastchar != " " && lastchar != "\n") {
    body.editAsText().insertText(alltext.length, "\n");
    alltext = body.getText();
  }

  var arr_alltext = alltext.split(/[\s\n]/);
  var pagewords = new Object;
  var pagewordsOrig = new Object;
  var pagewordsOrigOffset = new Object;
  var offset = 0;
  var curWord = "";
  var cnt = 0;
  
  for (var i = 0; i < arr_alltext.length; i++) {
    curWord = arr_alltext[i];
    if (StringHasSimeioStiksis(curWord)) {
      curWord = replaceSimeiaStiksis(curWord);
      var arr3 = curWord.split(" ");
      for (var k = 0; k < arr3.length; k++) {
        curWord = arr3[k];
        pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~@#$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
        pagewordsOrig["" + (cnt+1).toString()] = curWord;
        pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
        offset += curWord.length;
        cnt++;
      }
      offset++;
    } else {
      pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~@#$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
      pagewordsOrig["" + (cnt+1).toString()] = curWord;
      pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
      offset += curWord.length + 1;
      cnt++;
    }
  }

  var respTString = "";

  var url = 'https://www.example.org/spellchecker.php';
  var data = {
    "Text" : JSON.stringify(pagewords),
    "idOffset" : "0",
    "lexID" : "8",
    "userEmail" : "test@example.org"
  };
  var payload = JSON.stringify(data);
  var options = {
    "method" : "POST",
    "contentType" : "application/json",
    "payload" : payload
  };
  //var t11 = new Date().getTime();
  console.time("POST time");
  var response = UrlFetchApp.fetch(url, options);
  console.timeEnd("POST time");
  //var t22 = new Date().getTime();
  var resp = response.getContentText();
  respTString = resp;
  var spellchecked = JSON.parse(respTString);

  var style = {};
  for (var k in pagewords){
      if (pagewords.hasOwnProperty(k)) {
          if (spellchecked.hasOwnProperty(k)) {
            if (spellchecked[k].substr(0, 1) == "1") {
              style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
            }            
            if (spellchecked[k].substr(0, 1) == "0") {
              style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
            }
            if (spellchecked[k].substr(0, 1) == "4") {
              style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
            }
            if (pagewordsOrigOffset[k] < alltext.length) {
              body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
            }
          }
      }
  }

  //var t2 = new Date().getTime();
  console.timeEnd("function time")
  return {
    "pagewords" : pagewords,
    "pagewordsOrig" : pagewordsOrig,
    "pagewordsOrigOffset" : pagewordsOrigOffset,
    "spellchecked" : spellchecked
  }
}

预先感谢您的任何帮助。

编辑:我根据建议更新了代码以使用 console.time ,结果是:

total time: 2048.001953125 ms
Jun 21, 2021, 3:01:40 PM    Debug   POST time: 809ms
Jun 21, 2021, 3:01:41 PM    Debug   function time: 1408ms

所以问题不在于如何测量时间。函数时间是 1400 毫秒,而返回时间是 2000 毫秒,相差 600 毫秒,POST 时间是惊人的 800 毫秒,而不是在 VB.net 中进行完全相同的 POST 调用需要 200 毫秒。

标签: javascriptgoogle-apps-script

解决方案


使用 console.time() 和 console.timeEnd(): https ://developers.google.com/apps-script/reference/base/console

我为你修改了代码。console.timeEnd() 会自动在控制台中输出持续时间,因此我为您删除了显示时差的警报。

您可能希望我用作参数的字符串作为某种常量变量,因此没有使用两次的魔术字符串。我希望这对你有用。

function runSpellChecking() {
    gb_IsSpellcheckingRunning = true;
    //gb_isAutoCorrecting = false;
    gi_CorrectionCurrWordIndex = -1;
    $("#btnStartCorr").attr("disabled", true);

    $("#divMistakes").html("");
    this.disabled = true;
    //$('#error').remove();
    var origin = $('input[name=origin]:checked').val();
    var dest = $('input[name=dest]:checked').val();
    var savePrefs = $('#save-prefs').is(':checked');
    console.time("total time");
    google.script.run
        .withSuccessHandler(
          function(textAndTranslation, element) {
            if (gb_IsSpellCheckingEnabled) {
              console.timeEnd("total time");
              go_TextAndTranslation = JSON.parse(JSON.stringify(textAndTranslation));
              var pagewords = textAndTranslation.pagewords;
              var spellchecked = textAndTranslation.spellchecked;
              //irrelevant code follows below...
            }
          })
        .withFailureHandler(
          function(msg, element) {
            showError(msg, $('#button-bar'));
            element.disabled = false;
          })
        .withUserObject(this)
        .executeSpellChecking(origin, dest, savePrefs);
}

function executeSpellChecking(origin, dest, savePrefs) {
  console.time("function time");
  var body = DocumentApp.getActiveDocument().getBody();
  var alltext = body.getText();
  var lastchar = alltext.slice(-1);
  if (lastchar != " " && lastchar != "\n") {
    body.editAsText().insertText(alltext.length, "\n");
    alltext = body.getText();
  }

  var arr_alltext = alltext.split(/[\s\n]/);
  var pagewords = new Object;
  var pagewordsOrig = new Object;
  var pagewordsOrigOffset = new Object;
  var offset = 0;
  var curWord = "";
  var cnt = 0;
  
  for (var i = 0; i < arr_alltext.length; i++) {
    curWord = arr_alltext[i];
    if (StringHasSimeioStiksis(curWord)) {
      curWord = replaceSimeiaStiksis(curWord);
      var arr3 = curWord.split(" ");
      for (var k = 0; k < arr3.length; k++) {
        curWord = arr3[k];
        pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~@#$%^&*()_|+\-="<>\{\}\[\]\\\/]/gi, '');
        pagewordsOrig["" + (cnt+1).toString()] = curWord;
        pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
        offset += curWord.length;
        cnt++;
      }
      offset++;
    } else {
      pagewords["" + (cnt+1).toString()] = curWord.replace(/[`~@#$%^&*()_|+\-="<>\{\}\[\]\\\/\n]/gi, '');
      pagewordsOrig["" + (cnt+1).toString()] = curWord;
      pagewordsOrigOffset["" + (cnt+1).toString()] = offset;
      offset += curWord.length + 1;
      cnt++;
    }
  }

  var respTString = "";

  var url = 'https://www.example.org/spellchecker.php';
  var data = {
    "Text" : JSON.stringify(pagewords),
    "idOffset" : "0",
    "lexID" : "8",
    "userEmail" : "test@example.org"
  };
  var payload = JSON.stringify(data);
  var options = {
    "method" : "POST",
    "contentType" : "application/json",
    "payload" : payload
  };
  console.time("POST time");
  var response = UrlFetchApp.fetch(url, options);
  console.timeEnd("POST time");
  var resp = response.getContentText();
  respTString = resp;
  var spellchecked = JSON.parse(respTString);

  var style = {};
  for (var k in pagewords){
      if (pagewords.hasOwnProperty(k)) {
          if (spellchecked.hasOwnProperty(k)) {
            if (spellchecked[k].substr(0, 1) == "1") {
              style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#000000";
            }            
            if (spellchecked[k].substr(0, 1) == "0") {
              style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#FF0000";
            }
            if (spellchecked[k].substr(0, 1) == "4") {
              style[DocumentApp.Attribute.FOREGROUND_COLOR] = "#0000FF";
            }
            if (pagewordsOrigOffset[k] < alltext.length) {
              body.editAsText().setAttributes(pagewordsOrigOffset[k], pagewordsOrigOffset[k] + pagewordsOrig[k].length, style);
            }
          }
      }
  }

  console.timeEnd("function time");
  return {
    "pagewords" : pagewords,
    "pagewordsOrig" : pagewordsOrig,
    "pagewordsOrigOffset" : pagewordsOrigOffset,
    "spellchecked" : spellchecked
  }
}

推荐阅读