Google apps script 应用程序脚本:加载电子表格时的竞争条件,是否提供了不正确的数据?

Google apps script 应用程序脚本:加载电子表格时的竞争条件,是否提供了不正确的数据?,google-apps-script,google-sheets,google-sheets-formula,importrange,Google Apps Script,Google Sheets,Google Sheets Formula,Importrange,我在应用程序脚本web应用程序上遇到了一个有趣的问题。启动时,在处理程序中,代码通过getRangeByName从电子表格a获取一小部分数据(大约20个值)。电子表格A并不复杂,但它有4页,其中两页是从电子表格B加载的(使用importRange)。这两个页面中的每一页都加载了一个ImportRange,每个页面都会加载大约6000个单元格 问题出在这里。当用户单击web应用程序URL时,getRangeByName加载的数据在很多时候(可能是25%的尝试)是不正确的。返回的数据是#值而不是实际

我在应用程序脚本web应用程序上遇到了一个有趣的问题。启动时,在处理程序中,代码通过
getRangeByName
从电子表格a获取一小部分数据(大约20个值)。电子表格A并不复杂,但它有4页,其中两页是从电子表格B加载的(使用
importRange
)。这两个页面中的每一页都加载了一个
ImportRange
,每个页面都会加载大约6000个单元格

问题出在这里。当用户单击web应用程序URL时,
getRangeByName
加载的数据在很多时候(可能是25%的尝试)是不正确的。返回的数据是
#值而不是实际的电子表格数据。应该返回的实际数据是从链接(
importRange
)电子表格派生的文本(人名)

这通常发生在启动时(在
doGet
),但我也曾在用户单击按钮后看到过这种情况

它看起来很像是在电子表格通过
importRange
完成数据加载之前返回的
getRangeByName
。这并不是什么大问题-我刚刚更改了脚本,使其在
getRangeByName
上循环,并使用
睡眠
,直到给定的单元格具有已知的正确值。经过有限的测试后,修复方案似乎有效。然而,这看起来确实相当业余。还有谁见过这个吗?这是一个已知的问题,是否有一个“适当”的方法来处理

第一次编辑

睡眠/重读修复不起作用,我添加了下面的代码。我调用它而不是普通的
openById
来打开电子表格。此代码最初仅包括第二次
flush
调用。这段代码仍然偶尔会失败,甚至在第二次抛出时失败,尽管这似乎是不可能的。这里发生的事情是GAS(最终)设法在for循环中获得正确的电子表格数据,然后退出for循环并尝试获取完全相同的数据,而数据现在是不正确的

第二次编辑

我在下面的代码中添加了第二个刷新操作,它位于第一次调用
getRangeByName
之前,正如注释中所建议的那样。没有区别;第三次调用
InputSpreadsheetOpen
(在处理程序中)时,代码失败(第二次抛出)

/**
*打开时,围绕谷歌竞争条件展开工作
*输入电子表格。如果我们不能从一个范围中读出我们所期望的
*在电子表格中,只需睡眠并重试。
*/
函数输入SpreadsheetOpen(){
var ss=电子表格应用程序openById(输入);
var数据;
SpreadsheetApp.flush();//应该完全没有意义。。。
对于(变量i=0;i++){
data=ss.getRangeByName(“名称”).getValues();
如果(数据==null)
throw(“'swimernames'未定义。”);//电子表格错误
如果(数据[0]==第一个\u名称)
break;//获得了预期值

如果(我已经在getRangeByName之前尝试了SpreadsheetApp.flush()),如果flush不起作用,您也可以直接从脚本中的电子表格B加载数据。添加了flush(见上文),但在打开电子表格时似乎毫无意义。我无法在脚本中直接读取电子表格B-它是电子表格a所必需的,并且脚本需要电子表格a的输出,而不是B的内容。您尝试过SpreadsheetApp.flush()吗在getRangeByName之前?最重要的一个词是“before”。它在第二个getRangeByName之前。如果它能工作,那肯定足够了吗?这是第二个最终失败的调用。无论如何,我会尝试一下。
/**
 * Work around what appears to be a Google race condition when opening
 * the input spreadsheet. If we can't read what we expect from a range
 * in the spreadsheet, just sleep and try again.
 */
function InputSpreadsheetOpen() {
  var ss = SpreadsheetApp.openById(INPUT_SS);
  var data;

  SpreadsheetApp.flush();         // should be completely pointless...
  for(var i=0; ; i++) {
    data = ss.getRangeByName("swimmerNames").getValues();
    if(data == null)
      throw(" 'swimmerNames' is not defined."); // spreadsheet error
    if(data[0] == FIRST_NAME)
      break;                                    // got expected value
    if(i <10) {                                 // Google error?
      Utilities.sleep(500);                     // ms; total 5s
      continue;
    } else
      throw("The server appears to be busy. Please refresh the browser page.");
  }

  SpreadsheetApp.flush();         // should be completely pointless...
  data = ss.getRangeByName("swimmerNames").getValues();
  if(data[0] != FIRST_NAME)
    throw("GAS is broken. Reload and pray.");
  return ss;
} // InputSpreadsheetOpen()