2

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

这就是问题所在。当用户点击 Web 应用 URL 时,很多时候(可能有 25% 的尝试)加载的数据getRangeByName是不正确的。返回的数据#VALUE!不是实际的电子表格数据。应该返回的实际数据是源自链接 ( importRange) 电子表格的文本(人名)。

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

它看起来很像getRangeByName在电子表格完成加载数据之前返回importRange。这并不是一个真正的主要问题 - 我刚刚更改了脚本,以便它使用 , 循环getRangeByNamesleep直到给定单元格具有已知的正确值。经过有限的测试,该修复似乎有效。然而,这似乎相当业余。有没有其他人看过这个?这是一个已知问题,是否有“正确”的方法来处理这个问题?

第一次编辑

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

第二次编辑

getRangeByName正如评论中所建议的,我在下面的代码中添加了第二次刷新操作,这是在第一次调用之前。没有不同; 代码在第三次调用(在处理程序中)时失败(再次与第二次抛出)。InputSpreadsheetOpen

/**
 * 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()
4

0 回答 0