Search code examples
javascriptgoogle-apps-script

Execution order of GS files in a Project


Where can I read documentation concerning the execution order rules for GS files?

To dimension the problem I created two trivial objects, each in their own file.

1_File.gs

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

0_File.gs

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

A call such as ...

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

... gets the error ...

TypeError: Cannot read property "sayName" from undefined.

If I move the code from 1_File.gs into 0_File.gs, and vice versa, then there is no error and the log shows correctly ...

I'm A : [ I'm A ]

Renaming 0_File.gs to 2_File.gs doesn't affect execution order either, so I assume that order depends on which file gets created first.

Is there no concept of "include" or "import" that would allow me to make order of execution explicit?


Solution

  • Where can I read documentation concerning the execution order rules for GS files?

    There is no such documentation and I think will not be any time published. In similar way, an initialization order of the static variables in C++ is also undefined and depends on compiler/linker.

    Is there no concept of "include" or "import" that would allow me to make order of execution explicit?

    Yes, there is no "includes", "imports" and even "modules", but there are libraries.

    Also there is a workaround by using a closure. Bellow is a sample code. By executing the test function the log contains c.d. The idea is to have in all gs files a function started with init. In these functions all global variables are instanced. The anonymous closure is executed during the Code.gs file instancing and calls all "init" functions of all gs files.

    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' };
    };