【问题标题】:Global Variable Bug in Google Apps Script Server SideGoogle Apps 脚本服务器端的全局变量错误
【发布时间】:2020-02-14 22:55:00
【问题描述】:

我正在尝试在 Apps 脚本中创建全局变量并避免使用 UserProperties 等内置函数。避免 UserProperties 的原因是因为我所有的 Web 应用程序用户都将共享相同的变量,这将导致他们的帐户混合在一起。我想创建具有生命周期的全局变量,直到您关闭选项卡/窗口。我无法使用用户属性,因为我需要以我自己的身份运行脚本,因为我在此 Web 应用程序中我的帐户下的电子表格中进行搜索。

function extractData(row){
  extractEmail(row);
  extractPoints(row);
  extractUsername(row);
  extractName(row);
  extractType(row);
  extractFamily(row);
  return "success";
}

function extractEmail(row){
  try{
    var url = "https://docs.google.com/spreadsheets/d/1pIC6Lyx4Q0ZjEA5GURZ3gA5qLmUJ0_7yGPJQmr6-GnQ/edit?usp=sharing";
    var sheet = SpreadsheetApp.openByUrl(url);
    var subsheet = sheet.getSheetByName("Accounts");
    var col = 2
    Gemail = String(subsheet.getRange(Number(row), col).getValue());
  }
  catch(error){
    Logger.log(error.message);
    }
}

function extractPoints(row){
  var url = "https://docs.google.com/spreadsheets/d/1pIC6Lyx4Q0ZjEA5GURZ3gA5qLmUJ0_7yGPJQmr6-GnQ/edit?usp=sharing";
  var sheet = SpreadsheetApp.openByUrl(url);
  var subsheet = sheet.getSheetByName("Accounts");
  var col = 6;
  Gpoints = Number(subsheet.getRange(Number(row), col).getValue());
}

function extractUsername(row){
  var url = "https://docs.google.com/spreadsheets/d/1pIC6Lyx4Q0ZjEA5GURZ3gA5qLmUJ0_7yGPJQmr6-GnQ/edit?usp=sharing";
  var sheet = SpreadsheetApp.openByUrl(url);
  var subsheet = sheet.getSheetByName("Accounts");
  var col = 4;
  Gusername = String(subsheet.getRange(row, col).getValue());
}

function extractName(row){
  var url = "https://docs.google.com/spreadsheets/d/1pIC6Lyx4Q0ZjEA5GURZ3gA5qLmUJ0_7yGPJQmr6-GnQ/edit?usp=sharing";
  var sheet = SpreadsheetApp.openByUrl(url);
  var subsheet = sheet.getSheetByName("Accounts");
  var col = 3;
  Gname = String(subsheet.getRange(row, col).getValue());
}

function extractType(row){
  var url = "https://docs.google.com/spreadsheets/d/1pIC6Lyx4Q0ZjEA5GURZ3gA5qLmUJ0_7yGPJQmr6-GnQ/edit?usp=sharing";
  var sheet = SpreadsheetApp.openByUrl(url);
  var subsheet = sheet.getSheetByName("Accounts");
  var col = 7;
  Gtype = String(subsheet.getRange(row, col).getValue());
}

function extractFamily(row){
  var url = "https://docs.google.com/spreadsheets/d/1pIC6Lyx4Q0ZjEA5GURZ3gA5qLmUJ0_7yGPJQmr6-GnQ/edit?usp=sharing";
  var sheet = SpreadsheetApp.openByUrl(url);
  var subsheet = sheet.getSheetByName("Accounts");
  var col = 12;
  Gfamily = String(subsheet.getRange(row, col).getValue());
  Logger.log(Gfamily);
}

function definer(){
  try{
  Utilities.sleep(5000);
  Logger.log(Gfamily);
  var data = [Gemail, Gname, Gusername, Gpoints, Gtype, Gfamily];
  return data;
  }
  catch(error){
    Logger.log(error.message);
  }
}

上面的代码是服务器端的。客户端调用每个函数以及已定义的行。客户端调用的第一个函数是extractData。记录全局变量 Gfamily 时,它会正确显示为 testers。在下一个函数之后:definer 从客户端调用,Gfamily 被记录为 null。如果我不清楚任何事情,请告诉我如何改进这个问题。以下是日志的屏幕截图: Screenshot: Stackdriver logs showing how Gfamily suddenly becomes undefined

【问题讨论】:

  • 听起来您正在寻找会话变量,而不是全局变量。我不知道Google App Scripts,所以不知道有没有这个。
  • 看起来确实如此,Session 类。 stackoverflow.com/questions/44573749/…
  • 我认为,在您的脚本中,当 launch() 在脚本编辑器中启用和不启用 V8 的情况下运行时,second() 中的Logger.log(globalVariable) 显示test。那么我可以问你关于复制globalVariable gets logged as null 问题的详细流程吗?顺便说一句,如果你想让用户使用相同的变量,使用getScriptProperties()而不是getUserProperties()怎么样?但是我不确定你的实际情况。所以如果这不是你想要的方向,我很抱歉。
  • 您也许可以使用 UserProperties 而不是 ScriptProperties。

标签: javascript google-apps-script


【解决方案1】:

您的前端(浏览器)会话与您的后端(服务器)会话是分开的。 Google 的服务器并没有真正跟踪用户是否关闭选项卡/窗口,因此您将不得不从前端管理会话,然后编写自己的服务器函数来正确识别会话。

要在多个用户之间共享一个值,我建议使用Script PropertiesScript Cache。您的网络应用程序的所有用户都可以使用存储在脚本属性/缓存中的值。如果一个用户更新该值,则新值将立即可供所有其他用户使用。我建议将它与Window.sessionStorage 一起使用,它会在页面会话结束时自动清除。因此,您可以将会话数据传递给服务器,然后手动跟踪会话何时结束。

但是,我真的不明白您打算如何使用依赖于多个用户会话的共享值。如果其中一位用户结束会话,共享值会发生什么变化?

这让我觉得可能有一些误解,特别是由于你的句子

避免使用 UserProperties 的原因是因为我所有的网络应用用户都将共享相同的变量,这将导致他们的帐户混合在一起。

不共享用户属性,除非您将应用部署到“Execute the app as me”。如果您这样做了,那么脚本将始终在同一个(您的)用户帐户下执行,并且所有用户属性共享。但是,如果您只是设置“以访问网络应用程序的用户身份执行应用程序”,那么您可以安全地使用用户属性/缓存,而不用担心混合帐户。 (用户属性/缓存的目的是避免跨帐户混合等范围问题 - 看看这个comparison table。)

【讨论】:

  • 感谢 Diego 的回答。我很抱歉我第一次问这个问题时不清楚。我刚刚更新了我的问题,希望现在更清楚了。这次我包含了我的实际代码的 sn-p。
  • @DavidFahim 将Gfamily 的值返回到前端并使用window.sessionStorage(上面提到的)保存它。然后在调用时将该值传递给definer()
猜你喜欢
  • 1970-01-01
  • 2015-05-19
  • 2015-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多