【问题标题】:GAS: How to change a global variable value and preserve its changed value when using the variable in a handler function?GAS:如何在处理函数中使用变量时更改全局变量值并保留其更改后的值?
【发布时间】:2013-12-13 23:26:33
【问题描述】:

我的脚本中有这个全局变量:

var targetDocId = 'No doc ID informed yet';

我正在尝试在我的主函数中更改这个全局变量的值:

function generatePersonDatasheet() {
  var target = createDuplicateDocument(template, docName);
  var link = target.getUrl();
  targetDocId = target.getId(); // <-------- HERE
  if (theses == 1){
    Logger.log("going to showList() ");
    return showList();
  }   
  showURL(docName, link); 
}

之后,我尝试在处理函数中访问更改后的全局变量值:

function submit(e){
  var numberOfItems = Number(e.parameter.checkbox_total);
  var thesesArrays = [];
  for(var i = 0; i < numberOfItems; i++){
    if(e.parameter['checkbox_isChecked_'+i] == 'true'){
      thesesArrays.push(fact_list[i]);
    }
  }
  for (var i = 0; i < thesesArrays.length; i++){
    var thesesId = thesesArrays[i][2];
    var thesesType = thesesArrays[i][1];        
    importTheses(targetDocId, thesesId, thesesType); // <-----HERE
  }
  return UiApp.getActiveApplication().close();
}

function importTheses(targetDocId, thesesId, thesesType) {
  var targetDoc = DocumentApp.openById(targetDocId);
  var targetDocParagraphs = targetDoc.getParagraphs();
  var targetDocElements = targetDocParagraphs.getNumChildren();

  var thesesDoc = DocumentApp.openById(thesesId);
  var thesesParagraphs = thesesDoc.getParagraphs();
  var thesesElements = thesesDoc.getNumChildren();

  var eltargetDoc=[];
  var elTheses=[];

  for( var j = 0; j < targetDocElements; ++j ) {
       var targetDocElement = targetDoc.getChild(j);
        eltargetDoc[j]=targetDocElement.getText();
       if(el[j]== thesesType){
           for( var k = 0; k < thesesParagraphs-1; ++k ) {
               var thesesElement = thesesDoc.getChild(k);
               elTheses[k] = thesesDoc.getText();
               targetDoc.insertParagraph(j, elTheses[k]);
         }
      }
   }
}

但是,只要我尝试更改 targetDocId,当它用作 importTheses(targetDocId, thesesId, thesesType); 的参数时,它仍然具有值“尚未通知文档 ID”,即使我已经更改了它,就好像程序有从一开始就运行。是这种“重置为原始值”行为的替代方法吗?或者我必须使用 scriptDB 或 ScriptProperties 来存储全局变量的更改值?

【问题讨论】:

    标签: javascript google-apps-script global-variables handler scope


    【解决方案1】:

    不,没有这样的选择。您必须使用 scriptProperties 或 scriptDb。一旦你的函数完成,一个全局的 vsriable 就会超出范围。每个外部脚本调用都从零开始。

    【讨论】:

    • 因此,当我转到处理程序函数时,我退出了我的主函数,并且在运行处理程序后,我无法返回并恢复到我转到处理函数?
    • 该处理函数不再在主函数的范围内。你不能那样做。当你的处理程序被调用时,main 很久以前就完成了,脚本再次从零加载。
    • "当你的处理程序被调用时,main 很久以前就完成了,脚本再次从零加载。"那是我的疑问!
    【解决方案2】:

    每个单独的脚本执行都在一个新的执行实例中完成。因此,在代码块之外定义的任何变量(也称为“全局”变量)对于该实例都是唯一的。当触发函数被事件调用时,它会在自己的实例中运行,并且它设置的任何全局值仅对该实例可见;例如,由电子表格或文档 UI 调用的另一个函数将拥有该非范围对象(全局)的自己的版本。

    targetDocId 的定义和检索将是Cache Service 的一个很好的应用。note

    function get_targetDocId () {
      var cache = CacheService.getPublicCache();
      var cached = cache.get("targetDocId");
      if (cached != null) {
        return cached;
      }
      var target = createDuplicateDocument(template, docName);  /// Need to add handling for pre-existing document
      var link = target.getUrl();
      var contents = target.getId();
      cache.put("targetDocId", contents, 1500); // cache for 25 minutes
      return contents;
    }
    

    现在不要尝试使用全局变量,只需调用此函数:

    ...
    var targetDoc = DocumentApp.openById(get_targetDocId());
    ...
    

    note 缓存服务是可用于 Google Apps 脚本的持久存储示例之一。 Properties Service 是在编写此答案后引入的,它是一种在执行实例之间持久化“全局”变量的更轻量级的方法。


    观察:您似乎在为tempatedocName 使用全局(静态),因为generatePersonDatasheet() 没有参数。您可以简单地即时生成 targetDocId。

    错误:正如它所写,get_targetDocId() 将在每次需要刷新缓存(15 分钟)时创建一个新的docName 副本。您应该添加对预先存在文件的可能性的处理。 (您现有的onOpen() 也是如此。)

    【讨论】:

    • 非常丰富的答案!我会尝试使用缓存服务!谢谢,@Mogsdad!
    猜你喜欢
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 2013-10-04
    • 1970-01-01
    • 2020-09-04
    • 1970-01-01
    相关资源
    最近更新 更多