项目中GS文件的执行顺序

时间:2012-10-02 09:38:19

标签: google-apps-script

在哪里可以阅读有关GS文件执行顺序规则的文档?

为了确定问题的维度,我创建了两个简单的对象,每个对象都在自己的文件中。

1_File.gs

var ObjB = new Object();
ObjB.sayName = "[" + ObjA.sayName + "]";

0_File.gs

var ObjA = new Object();
ObjA.sayName = " I'm A ";

诸如......之类的电话。

Logger.log(ObjA.sayName + " : " + ObjB.sayName);

...得到错误......

TypeError: Cannot read property "sayName" from undefined.

如果我将代码从1_File.gs移动到0_File.gs,反之亦然,则没有错误,日志显示正确...

  

我是A:[我是A]

将0_File.gs重命名为2_File.gs也不会影响执行顺序,因此我假设该顺序取决于首先创建的文件。

是否没有“include”或“import”概念允许我明确执行执行顺序?

6 个答案:

答案 0 :(得分:10)

  

在哪里可以阅读有关GS文件执行顺序规则的文档?

没有这样的文件,我认为不会发布任何时间。以类似的方式,C ++中静态变量的初始化顺序也是未定义的,并且依赖于编译器/链接器。

  

是否没有“include”或“import”概念允许我明确执行执行顺序?

是的,没有“包含”,“导入”甚至“模块”,但有libraries

还有一个使用闭包的解决方法。贝娄是一个示例代码。通过执行测试功能,日志包含c.d。我们的想法是在所有gs个文件中包含一个以init开头的函数。在这些函数中,所有全局变量都是实例化的。匿名闭包在Code.gs文件实例化期间执行,并调用所有gs文件的所有“init”函数。

<强> Code.gs

var c;

function callAllInits_() {
  var keys = Object.keys(this);
  for (var i = 0; i < keys.length; i++) {
    var funcName = keys[i];
    if (funcName.indexOf("init") == 0) {
      this[funcName].call(this);
    }
  }
}

(function() {
  callAllInits_();
  c = { value : 'c.' + d.value };
})();

function test() {
  Logger.log(c.value);
}

<强> d.gs

var d;

function initD() {
  d = { value : 'd' };
};

答案 1 :(得分:2)

我通过在每个文件中创建一个类并确保每个类在原始Code.gs(我重命名为_init.gs)中实例化来解决此问题。实例化每个类充当include的一种形式,并确保在执行任何操作之前一切都已就绪。

_init.gs

// These instances can now be referred to in all other files
var Abc  = new _Abc();
var Menu = new _Menu();
var Xyz  = new _Xyz();
var Etc  = new _Etc();

// We need the global context (this) in order to dynamically add functions to it
Menu.createGlobalFunctions(this);

function onInstall(e) {
  onOpen(e);
}

function onOpen(e) {
  Menu.build();
}

课程通常如下:

menu.gs

function _Menu() {
  this.build = function() {
    ...
  }

  ...
}

答案 2 :(得分:2)

如果您有多个继承级别,则需要提供初始化函数名称,如init000Fooinit010Barinit020Baz,然后按名称对init函数进行排序执行。这将确保首先评估init000Foo,然后Bar,然后Baz

function callAllInits() {
  var keys = Object.keys(this);
  var inits = new Array();
  for (var i = 0; i < keys.length; i += 1) {
    var funcName = keys[i];
    if (funcName.indexOf("init") == 0) {
      inits.push(funcName);
    }
  }

  inits.sort();
  for (var i = 0; i < inits.length; i += 1) {
    // To see init order:
    // Logger.log("Initializing " + inits[i]);
    this[inits[i]].call(this);
  }
}

答案 3 :(得分:1)

Google Apps脚本中没有此类订单。它完全取决于您声明这些对象的位置以及调用函数的方式。 你能解释一下如何以及何时调用你的Logger.log()代码。 另外,你什么时候声明你的对象objA和objB? 这些将有助于我们提供更好的答案

答案 4 :(得分:1)

其他答案(即,不写任何引用其他文件中对象的顶级代码)描述了避免此问题的理想方法。但是,如果您已经编写了大量代码并重写它是不可行的,则有一种解决方法:

Google App Script似乎按照创建顺序加载代码文件。首先是最旧的文件,然后是下一个,最后创建的文件是最后一个。这是&#34;按字母顺序排序文件时编辑器中显示的顺序&#34;未经检查。

因此,如果您按此顺序拥有文件:

  • Code.gs
  • 1_File.gs(取决于0_File.gs)
  • 0_File.gs

一个简单的解决方法是制作1_File.gs的副本,然后删除原始文件,有效地将其移动到列表的末尾。

  1. 点击1_File.gs旁边的三角形,然后选择&#34;制作副本&#34;
    • Code.gs
    • 1_File.gs
    • 0_File.gs
    • 1_File copy.gs
  2. 点击1_File.gs旁边的三角形,然后选择&#34;删除&#34;
    • Code.gs
    • 0_File.gs
    • 1_File copy.gs
  3. 单击1_File copy.gs旁边的三角形,然后选择&#34;重命名&#34;,然后删除&#34;拷贝&#34;从最后。
    • Code.gs
    • 0_File.gs
    • 1_File.gs
  4. 现在0_File.gs在1_File.gs之前加载。

答案 5 :(得分:0)

这是我将如何做到这一点...

function include(filename) {
  return ContentService.createTextOutput(filename);
}

function main() {
  include('Obj A');
  include('Obj B');
  Logger.log(ObjA.sayName + " : " + ObjB.sayName);
}

Obj A

var ObjA = new Object();
ObjA.sayName = " I'm A ";

Obj B

var ObjB = new Object();
ObjB.sayName = "[" + ObjA.sayName + "]";