How to use global variables while avoiding permission errors?

风格不统一 提交于 2020-12-07 16:38:55

问题


See the below example,

function doSomething1(){/*needs ss*/const ss = SpreadsheetApp.openById(/*SPREADSHEET_ID*/);}
function doSomething2(){/*needs ss*/const ss = SpreadsheetApp.openById(/*SPREADSHEET_ID*/);}
function doItAll(){
  doSomething1();
  doSomething2();
}

Instead of calling Spreadsheet in both functions, this could be simplified using globals as

const ss = SpreadsheetApp.openById(/*SPREADSHEET_ID*/);
function doSomething1(){/*do something with ss*/}
function doSomething2(){/*do something with ss*/}
function doItAll(){
  doSomething1();
  doSomething2();
}

The problem here can be solved without using global variables by simply passing ss variable between the functions. But This will get much more complicated with multiple functions requiring access to the ss variable. And passing ss is cumbersome. There aren't many ways to avoid a global in Apps script. Modules aren't supported. If you use a IIFE, all functions are hidden from the IDE- making a function call from IDE or anywhere else impossible. Using a global here is much more elegant. But problems arise if I have a simple trigger:

const ss = SpreadsheetApp.openById(/*SPREADSHEET_ID*/);
function doSomething1(){/*do something with ss*/}
function doSomething2(){/*do something with ss*/}
function doItAll(){
  doSomething1();
  doSomething2();
}
function onOpen(){/*Adds a menu*/}

The menu addition onOpen will fail because this line is loaded SpreadsheetApp.openById(/*SPREADSHEET_ID*/) before onOpen and that line requires permissions/authorizations while onOpen being a simple trigger doesn't run with any code requiring authorization.

How to declare globals without running into authorization errors?


回答1:


This issue can be solved by using a getter. A getter executes the code only when called from anywhere, thus encapsulating the execution of the code in global context. But the getter will execute on each call to the variable. If ss is called in two functions, SpreadsheetApp.openById is executed twice. We can avoid this using lazy loading technique mentioned in the MDN.

const config = {
  get ss() {
    delete this.ss;
    return (this.ss = SpreadsheetApp.openById(/*SPREADSHEET_ID*/));
  },
};
function doSomething1(){/*do something with config.ss*/}
function doSomething2(){/*do something with config.ss*/}
function doItAll(){
  doSomething1();
  doSomething2();
}
function onOpen(){/*Adds a menu*/}

Here, We use a getter inside a object instead of directly declaring the ss. Used this way, SpreadsheetApp.openById() is never called in global scope, though it is declared in global scope. It is only loaded, when doSomething1 is executed. In addition, the method is not called again when it is accessed from doSomething2, because the getter is deleted on first access and replaced with the actual value.

Although the code becomes a bit bulky, this solves many problems and is much more elegant.



来源:https://stackoverflow.com/questions/65150194/how-to-use-global-variables-while-avoiding-permission-errors

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!