如何在 Google Apps Script Webapp 上为并发用户提供便利?
How can I facilitate concurrent users on a Google Apps Script Webapp?
我目前正在创建一个可以读取和写入 Google Sheet 的网络应用程序。它本质上是一个表单应用程序,它从 HTML 表单获取输入,使用 appendRow()
将其写入 sheet (随后使用 getRange()
和 setValue()
来将更多数据附加到该行)。每行代表正在填写的表单的一个实例。请参阅写入过程的示例代码。
/*
Function that is called in Index.html whenever the 'Next' button pressed. This
gets all inputs from HTML form and stores them in the spreadsheet.
Parameters:
inputArray: a 1x3 array which contains the owner, reference and type of scale.
*/
function addProjectInputs(inputArray) {
var sheetName = "Inputs";
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName(sheetName);
Logger.log(sheet);
var d = new Date();
var tz = spreadsheet.getSpreadsheetTimeZone();
var d = [Utilities.formatDate(d,tz, "dd/MM/yyyy")];
var data = d.concat(inputArray);
Logger.log(data);
sheet.appendRow(data);
}
/* Function to append further data onto the row created from
addProjectInputs() */
function addFurtherInputs(idlerArray) {
var sheetName = "Inputs";
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName(sheetName);
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn()-42;
var arrayEmpty = idlerArray.every(function(i) { return i === ''; });
Logger.log(arrayEmpty);
if (arrayEmpty !== true) {
for (i = 0; i < idlerArray.length; i++) {
var range3 = sheet.getRange(lastRow,lastColumn+1+i,1,1);
range3.setValue(idlerArray[i]);
}
}
}
应用程序的摘要页面(第5页,在所有编写步骤后出现)然后读取此数据(使用.getRange().getValues()
),然后将它们显示在页面上。
当一个用户使用它时,它工作正常 - 但是这个应用程序将被最多 20 人使用,可能同时使用。这是一个问题。例如,如果第二个用户开始使用该应用程序,他们的数据将通过添加新行开始覆盖第一个用户的数据,因此 'archiving' 第一个用户的数据。我遇到了以下可能的解决方案:
- 利用 LockService 强制一次只能让一个人使用该应用程序(并不理想,因为该应用程序将用于报价客户并且不想让用户等待)。
- 多线程
- 堆栈
我不确定 2 或 3 在 GAS 中如何工作,甚至可能。谁能说明一下是否可以为多个用户提供便利,以及如何?
提前致谢
我尝试了所有这些解决方案。
- LockService 即使对于大型 sheet 和更多用户也能很好地工作。您需要跟踪用户的操作频率。如果你不使用模拟的网络套接字行为,你通常什么都不怕。
- 多线程在这里不适用。
- 堆栈。如果我没理解错的话,堆栈是根据 sheet 和公式组织的。通常我按访问级别和操作类型划分我的表格应用程序。关于访问一切都很清楚。动作类型:推、计算、拉。每个 sheet 只有一个动作。我使用
appendRow
一元条目进行推送。而且我还使用 类 来计算推送中的内容。这使我可以节省一个电话,而不是在我写信后每次都接听 pull.getDataRange().getValues()
。我使用公式,以便拉动始终相关。你必须熟悉"slice of the past"、"balances for the period"的概念才能实现这一点。
可能有点模糊,因为我的英语说得不好。我很抱歉。
我不会锁定,而是通过为每个用户会话生成一个唯一 ID 来解决这个问题,您可以将其存储在 sheet 中并在以后用于匹配值。
在您的入口点 [可能是 doGet(),可能是 doPost()],生成一个带有 var session_id = Utilities.getUuid();
的 UUID
然后将该会话 ID 传递给您的模板,并将其包含在所有返回到 Apps 脚本的未来请求中。
将 UUID 写入 addProjectInputs()
函数中 sheet 的列,然后修改 addFurtherInputs()
函数以根据 UUID 定位正确的行,(而不是总是采取最后一个)并将您的更新写入该行。
这种方法保证您可以让许多用户工作而不必担心相互覆盖,并且不会因锁定而延迟。
见https://developers.google.com/apps-script/reference/utilities/utilities#getUuid()
我目前正在创建一个可以读取和写入 Google Sheet 的网络应用程序。它本质上是一个表单应用程序,它从 HTML 表单获取输入,使用 appendRow()
将其写入 sheet (随后使用 getRange()
和 setValue()
来将更多数据附加到该行)。每行代表正在填写的表单的一个实例。请参阅写入过程的示例代码。
/*
Function that is called in Index.html whenever the 'Next' button pressed. This
gets all inputs from HTML form and stores them in the spreadsheet.
Parameters:
inputArray: a 1x3 array which contains the owner, reference and type of scale.
*/
function addProjectInputs(inputArray) {
var sheetName = "Inputs";
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName(sheetName);
Logger.log(sheet);
var d = new Date();
var tz = spreadsheet.getSpreadsheetTimeZone();
var d = [Utilities.formatDate(d,tz, "dd/MM/yyyy")];
var data = d.concat(inputArray);
Logger.log(data);
sheet.appendRow(data);
}
/* Function to append further data onto the row created from
addProjectInputs() */
function addFurtherInputs(idlerArray) {
var sheetName = "Inputs";
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName(sheetName);
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn()-42;
var arrayEmpty = idlerArray.every(function(i) { return i === ''; });
Logger.log(arrayEmpty);
if (arrayEmpty !== true) {
for (i = 0; i < idlerArray.length; i++) {
var range3 = sheet.getRange(lastRow,lastColumn+1+i,1,1);
range3.setValue(idlerArray[i]);
}
}
}
应用程序的摘要页面(第5页,在所有编写步骤后出现)然后读取此数据(使用.getRange().getValues()
),然后将它们显示在页面上。
当一个用户使用它时,它工作正常 - 但是这个应用程序将被最多 20 人使用,可能同时使用。这是一个问题。例如,如果第二个用户开始使用该应用程序,他们的数据将通过添加新行开始覆盖第一个用户的数据,因此 'archiving' 第一个用户的数据。我遇到了以下可能的解决方案:
- 利用 LockService 强制一次只能让一个人使用该应用程序(并不理想,因为该应用程序将用于报价客户并且不想让用户等待)。
- 多线程
- 堆栈
我不确定 2 或 3 在 GAS 中如何工作,甚至可能。谁能说明一下是否可以为多个用户提供便利,以及如何?
提前致谢
我尝试了所有这些解决方案。
- LockService 即使对于大型 sheet 和更多用户也能很好地工作。您需要跟踪用户的操作频率。如果你不使用模拟的网络套接字行为,你通常什么都不怕。
- 多线程在这里不适用。
- 堆栈。如果我没理解错的话,堆栈是根据 sheet 和公式组织的。通常我按访问级别和操作类型划分我的表格应用程序。关于访问一切都很清楚。动作类型:推、计算、拉。每个 sheet 只有一个动作。我使用
appendRow
一元条目进行推送。而且我还使用 类 来计算推送中的内容。这使我可以节省一个电话,而不是在我写信后每次都接听pull.getDataRange().getValues()
。我使用公式,以便拉动始终相关。你必须熟悉"slice of the past"、"balances for the period"的概念才能实现这一点。
可能有点模糊,因为我的英语说得不好。我很抱歉。
我不会锁定,而是通过为每个用户会话生成一个唯一 ID 来解决这个问题,您可以将其存储在 sheet 中并在以后用于匹配值。
在您的入口点 [可能是 doGet(),可能是 doPost()],生成一个带有 var session_id = Utilities.getUuid();
然后将该会话 ID 传递给您的模板,并将其包含在所有返回到 Apps 脚本的未来请求中。
将 UUID 写入 addProjectInputs()
函数中 sheet 的列,然后修改 addFurtherInputs()
函数以根据 UUID 定位正确的行,(而不是总是采取最后一个)并将您的更新写入该行。
这种方法保证您可以让许多用户工作而不必担心相互覆盖,并且不会因锁定而延迟。
见https://developers.google.com/apps-script/reference/utilities/utilities#getUuid()