google-apps-script - 使用 Google Apps Script Web App 轮询 Google 表格以进行更改的最佳方法?
问题描述
我正在开发一个谷歌应用程序脚本网络应用程序,以使其轮询谷歌表以进行更改/更新。目前,这可以是“内容”,也可以只是上次更新工作表的时间。我不能使用 gui/浏览器进行交互,因此请考虑运行 Web 应用程序的命令来自命令行上的 curl,并将文本内容返回到相同的内容。用户将根据需要重新启动 Web 应用程序,该应用程序设置为运行 @ 3 分钟。
我有一个有效的基本例程:
- 当应用程序启动时检查/获取原始状态(日期/内容)
- 运行一个计数器(每个)和一个计时器(睡眠),并在每次迭代中检查/获取当前状态(日期/内容)
- 在每次迭代中,针对当前状态测试原始状态。如果这些不同,则通过 ContentService 发送文本输出(消息、日期或当前内容。
我找到了三种适用于上述基础例程的方法:
A. 以数组形式获取工作表 dataRange 值 (sh.getDataRange().getValues();)
B. 获取 DriveApp LastUpdated 值 (DriveApp.getFileById(fileId).getLastUpdated();)
C. 获取修订列表最后修改日期(revisions = Drive.Revisions.list(fileId))
A效果很好,可以针对电子表格上的特定网格(工作表),但是对于大型数据集可能会出现问题?
function doGet() {
var ss = SpreadsheetApp.openById(fileId);
var sh = ss.getSheetByName('SheetName');
var rng = sh.getDataRange().getValues();
var msg = '';
for (var i = 0; i < 20; i++) {
SpreadsheetApp.flush();
var cur = sh.getDataRange().getValues();
i = i + 1;
if (JSON.stringify(rng) !== JSON.stringify(cur)) {
msg = JSON.stringify(cur);
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}
B 确实有效,但您似乎必须等待 1 到 5 分钟才能报告工作表上的更新。这“可能”没问题,但是对于进行更改的用户来说,它不够快
function doGet() {
var lastUpdated = DriveApp.getFileById(fileId).getLastUpdated();
var ss = SpreadsheetApp.openById(fileId);
var sh = ss.getSheetByName('Sheet2');
var rng = sh.getDataRange().getValues();
var msg = '';
for (var i = 0; i < 20; i++) {
SpreadsheetApp.flush();
var curUpdate = DriveApp.getFileById(fileId).getLastUpdated();
i = i + 1;
if (lastUpdated.toString() !== curUpdate.toString()) {
msg = lastUpdated.toString() + "\n" + curUpdate.toString();
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}
C 运行良好,几乎立即报告日期更改。不过,我有担心,读到1000 次修订后需要一个新令牌?
function doGet() {
var msg = '';
var revisions = Drive.Revisions.list(fileId);
var revision = revisions.items[revisions.items.length - 1];
var date = new Date(revision.modifiedDate);
for (var i = 0; i < 20; i++) {
var currevs = Drive.Revisions.list(fileId);
var currev = currevs.items[currevs.items.length - 1];
var curdate = new Date(currev.modifiedDate);
i = i + 1;
if ( date.toString() !== curdate.toString() ) {
msg = date.toString() + "\n" + curdate.toString();
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}
使用 B 是有意义的,但我找不到让 getLastupdated 的响应更直接的方法,也许是 C,使用修订是要走的路吗?我是否为此错过了“转到”方法,或者我的 Web 应用程序例程是否需要改进?
根据@Diego 的建议,我还通过 Advanced Drive Service 尝试了“modifiedDate”。这是一种享受:)
function doGet() {
var lastUpdated = Drive.getFileById(fileId).modifiedDate;
var msg = '';
for (var i = 0; i < 20; i++) {
var curUpdate = Drive.getFileById(fileId).modifiedDate;
i = i + 1;
if (lastUpdated.toString() !== curUpdate.toString()) {
msg = lastUpdated.toString() + "\n" + curUpdate.toString();
return ContentService.createTextOutput(msg);
}
Utilities.sleep(10000);
}
return ContentService.createTextOutput(msg);
}
解决方案
我看到在文件上使用修改日期与最新版本之间的区别在于,该文件还将报告对绑定脚本的更改。修订将仅限于电子表格上的更改并排除脚本更改。这可以在我下面的测试中看到,两者之间有几分钟的差异。
如果您想特别将范围限制为仅电子表格的更改,则将使用修订报告最准确的值。
function test() {
const fileId = FILE_ID;
console.log(getLastRevision(fileId)); // 2021-01-12T15:32:43.175Z
console.log(getLastUpdated(fileId)); // Tue Jan 12 2021 15:53:53 GMT+0000 (Greenwich Mean Time)
console.log(getLastUpdatedAdvanced(fileId)); // 2021-01-12T15:53:53.941Z
}
function getLastRevision(fileId) {
let response;
do {
response = Drive.Revisions.list(fileId, { maxResults: 1000 });
} while (response.nextPageToken);
return response.items[response.items.length - 1].modifiedDate;
}
function getLastUpdated(fileId) {
return DriveApp.getFileById(fileId).getLastUpdated();
}
function getLastUpdatedAdvanced(fileId) {
return Drive.Files.get(fileId).modifiedDate;
}
我不知道您可能希望电子表格有多少次修订,但使用 anextPageToken
非常简单。但是,如果电子表格将有数千个修订,并且您要经常轮询,那么它可能不是最有效的方法。
我无法用 复制延迟DriveApp.getFileById(fileId).getLastUpdated()
,但它并没有让我觉得不寻常。您可以尝试使用Advanced Drive 服务,就像您使用 Revisions 所做的那样,来获取modifiedDate
. 我不希望这会返回延迟值。正如您所指出的,这可能是您的最佳选择,因为您无需担心修订的数量,但请记住,它也反映了非电子表格的更新。
推荐阅读
- java - 位图未更新/显示旧值
- java - 通用 Guice 模块
- data-warehouse - 如何在 Synapse 中定义数据仓库单元?
- reactjs - 如何在 npm RunKit 上显示渲染的 React 组件?
- reactjs - 将更多图像从 react-native 应用程序上传到 firebase
- php - 使用 Supervisord - Apache 超时
- scala - SBT 总是在 Docker、docker-compose 上下载包/scala 库
- graph - 使用 GNUPlot 来自单个数据集的多个图
- ruby-on-rails - 在 Ruby 中将时间类增加 30 秒到分钟
- python-3.x - 正则表达式匹配与点组合在一起的字符串