是否可以在 Apps 脚本中获取新鲜的 Google 幻灯片演示数据?
Is it possible to get fresh Google Slides presentation data in AppsScript?
看来如果在AppsScript中使用SlidesApp.getActivePresentation()
,函数的结果不是新鲜的,而是事先准备好的东西。
场景
假设您有两个用户同时在 AppsScript 中执行以下功能:
function updateSlideText(slideId) {
// Request exclusive write access to the document
var lock = LockService.getDocumentLock();
lock.waitLock(15000);
// Perform changes
var presentation = SlidesApp.getActivePresentation();
var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
textBox.asShape().getText().setText('My text');
// Save and release lock
presentation.saveAndClose();
lock.releaseLock();
}
如果同时调用此函数两次,生成的幻灯片包含文本 "My textMy text"。
当我在锁定释放之前添加 Utilities.sleep(10000)
时,它会将第二次执行延迟 10 秒,但在这 10 秒之后我仍然得到相同的结果。另一方面,如果我真的延迟 调用 函数 10 秒,输出就没问题。
由此我得出结论,如果我调用 saveAndClose
并使用锁并不重要。一旦函数被调用,它总是会有陈旧的数据。有没有解决的办法?获取锁后不能请求加载新数据吗?
更多详情
更多伪代码以更好地说明问题用例:
// The addon frontend
websocket.onMessage((message) => {
if (message.type === 'pollUpdate') {
const slideWithPoll = store.getState().slides.find(
slide => slide.pollId === message.pollId
);
if (slideWithPoll.title !== message.poll.title) {
google.script.run.updateSlideText(slideWithPoll.id, message.poll.title);
}
}
});
我相信你的目标如下。
- 当 2 个用户是 运行 您的 Google 幻灯片的脚本时,同时,您想要单独 运行 脚本。
为此,这个答案怎么样?
问题和解决方法:
当我测试你的情况时,我可以确认与 My textMy text
相同的问题。当我多次测试时,在这种情况下,我认为 LockService 可能不会影响 Google Slides。因此,作为一种解决方法,我想建议使用 Web 应用程序作为包装器。因为已经知道 Web 应用程序可以 运行 由 LockService 独占。此解决方法的流程如下。
- 当脚本为运行时,脚本请求Web Apps。
- 在 Web Apps,您的脚本是 运行。
这样,即使脚本是运行,同时,脚本也可以与LockService独占运行。
用法:
本示例脚本的用法如下。请按照以下流程进行。
1。准备脚本。
当你的脚本被使用时,变成如下。请将以下脚本复制并粘贴到脚本编辑器中。请设置 MY_SLIDE_ID
和 MY_TEXTBOX_ID
.
function doGet() {
// This is your script.
var presentation = SlidesApp.getActivePresentation();
var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
var text = textBox.asShape().getText();
text.setText('My text');
return ContentService.createTextOutput("ok");
}
// Please run this function.
function main() {
var lock = LockService.getDocumentLock();
if (lock.tryLock(10000)) {
try {
const url = "https://script.google.com/macros/s/###/exec"; // Please set the URL of Web Apps after you set the Web Apps.
const res = UrlFetchApp.fetch(url);
console.log(res.getContentText())
} catch(e) {
throw new Error(e);
} finally {
lock.releaseLock();
}
}
}
2。部署 Web 应用程序。
- 在脚本编辑器上,通过"Publish" -> "Deploy as web app"打开一个对话框。
- Select "Me" 对于 "Execute the app as:"。
- 至此,脚本运行作为所有者。
- Select "Anyone, even anonymous" 对于 "Who has access to the app:"。
- 在这种情况下,请求不需要访问令牌。我认为我建议使用此设置来测试此解决方法。
- 当然,你也可以使用access token。届时请设置为"Anyone"。并且请将
https://www.googleapis.com/auth/drive.readonly
和 https://www.googleapis.com/auth/drive
的范围包含在访问令牌中。这些范围是访问 Web 应用程序所必需的。
- 单击 "Deploy" 按钮作为新按钮 "Project version"。
- 自动打开"Authorization required"的对话框。
- 点击"Review Permissions"。
- Select自己的账号。
- 在 "This app isn't verified" 单击 "Advanced"。
- 点击"Go to ### project name ###(unsafe)"
- 单击 "Allow" 按钮。
- 点击"OK"。
复制 Web Apps 的 URL。就像 https://script.google.com/macros/s/###/exec
.
- 当您修改 Google Apps 脚本时,请重新部署为新版本。这样,修改后的脚本就会反映到 Web 应用程序中。请注意这一点。
请将上述脚本的https://script.google.com/macros/s/###/exec
的URL设置为url
。并请重新部署 Web 应用程序。由此,最新的脚本被反映到Web Apps。所以请注意这一点。
4。测试此解决方法。
请运行 2 位用户同时使用main()
的功能,正如您所测试的那样。由此发现脚本是运行独占。在我的环境中,在这种情况下,我确认即使不使用 LockService,脚本也是独占的 运行。但我想推荐使用 LockService 以防万一。
注:
- 这是一个简单的示例脚本,用于解释此解决方法。所以大家在使用的时候,请根据自己的实际情况进行修改。
- 关于LockService可能不会影响到Google幻灯片的情况,目前阶段,虽然我不确定这是否是bug,但向the Google issue tracker报告如何?不幸的是,我在当前的 Google 问题跟踪器中找不到这个问题。
参考文献:
看来如果在AppsScript中使用SlidesApp.getActivePresentation()
,函数的结果不是新鲜的,而是事先准备好的东西。
场景
假设您有两个用户同时在 AppsScript 中执行以下功能:
function updateSlideText(slideId) {
// Request exclusive write access to the document
var lock = LockService.getDocumentLock();
lock.waitLock(15000);
// Perform changes
var presentation = SlidesApp.getActivePresentation();
var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
textBox.asShape().getText().setText('My text');
// Save and release lock
presentation.saveAndClose();
lock.releaseLock();
}
如果同时调用此函数两次,生成的幻灯片包含文本 "My textMy text"。
当我在锁定释放之前添加 Utilities.sleep(10000)
时,它会将第二次执行延迟 10 秒,但在这 10 秒之后我仍然得到相同的结果。另一方面,如果我真的延迟 调用 函数 10 秒,输出就没问题。
由此我得出结论,如果我调用 saveAndClose
并使用锁并不重要。一旦函数被调用,它总是会有陈旧的数据。有没有解决的办法?获取锁后不能请求加载新数据吗?
更多详情
更多伪代码以更好地说明问题用例:
// The addon frontend
websocket.onMessage((message) => {
if (message.type === 'pollUpdate') {
const slideWithPoll = store.getState().slides.find(
slide => slide.pollId === message.pollId
);
if (slideWithPoll.title !== message.poll.title) {
google.script.run.updateSlideText(slideWithPoll.id, message.poll.title);
}
}
});
我相信你的目标如下。
- 当 2 个用户是 运行 您的 Google 幻灯片的脚本时,同时,您想要单独 运行 脚本。
为此,这个答案怎么样?
问题和解决方法:
当我测试你的情况时,我可以确认与 My textMy text
相同的问题。当我多次测试时,在这种情况下,我认为 LockService 可能不会影响 Google Slides。因此,作为一种解决方法,我想建议使用 Web 应用程序作为包装器。因为已经知道 Web 应用程序可以 运行 由 LockService 独占。此解决方法的流程如下。
- 当脚本为运行时,脚本请求Web Apps。
- 在 Web Apps,您的脚本是 运行。
这样,即使脚本是运行,同时,脚本也可以与LockService独占运行。
用法:
本示例脚本的用法如下。请按照以下流程进行。
1。准备脚本。
当你的脚本被使用时,变成如下。请将以下脚本复制并粘贴到脚本编辑器中。请设置 MY_SLIDE_ID
和 MY_TEXTBOX_ID
.
function doGet() {
// This is your script.
var presentation = SlidesApp.getActivePresentation();
var textBox = presentation.getSlideById(MY_SLIDE_ID).getPageElementById(MY_TEXTBOX_ID);
var text = textBox.asShape().getText();
text.setText('My text');
return ContentService.createTextOutput("ok");
}
// Please run this function.
function main() {
var lock = LockService.getDocumentLock();
if (lock.tryLock(10000)) {
try {
const url = "https://script.google.com/macros/s/###/exec"; // Please set the URL of Web Apps after you set the Web Apps.
const res = UrlFetchApp.fetch(url);
console.log(res.getContentText())
} catch(e) {
throw new Error(e);
} finally {
lock.releaseLock();
}
}
}
2。部署 Web 应用程序。
- 在脚本编辑器上,通过"Publish" -> "Deploy as web app"打开一个对话框。
- Select "Me" 对于 "Execute the app as:"。
- 至此,脚本运行作为所有者。
- Select "Anyone, even anonymous" 对于 "Who has access to the app:"。
- 在这种情况下,请求不需要访问令牌。我认为我建议使用此设置来测试此解决方法。
- 当然,你也可以使用access token。届时请设置为"Anyone"。并且请将
https://www.googleapis.com/auth/drive.readonly
和https://www.googleapis.com/auth/drive
的范围包含在访问令牌中。这些范围是访问 Web 应用程序所必需的。
- 单击 "Deploy" 按钮作为新按钮 "Project version"。
- 自动打开"Authorization required"的对话框。
- 点击"Review Permissions"。
- Select自己的账号。
- 在 "This app isn't verified" 单击 "Advanced"。
- 点击"Go to ### project name ###(unsafe)"
- 单击 "Allow" 按钮。
- 点击"OK"。
复制 Web Apps 的 URL。就像
https://script.google.com/macros/s/###/exec
.- 当您修改 Google Apps 脚本时,请重新部署为新版本。这样,修改后的脚本就会反映到 Web 应用程序中。请注意这一点。
请将上述脚本的
https://script.google.com/macros/s/###/exec
的URL设置为url
。并请重新部署 Web 应用程序。由此,最新的脚本被反映到Web Apps。所以请注意这一点。
4。测试此解决方法。
请运行 2 位用户同时使用main()
的功能,正如您所测试的那样。由此发现脚本是运行独占。在我的环境中,在这种情况下,我确认即使不使用 LockService,脚本也是独占的 运行。但我想推荐使用 LockService 以防万一。
注:
- 这是一个简单的示例脚本,用于解释此解决方法。所以大家在使用的时候,请根据自己的实际情况进行修改。
- 关于LockService可能不会影响到Google幻灯片的情况,目前阶段,虽然我不确定这是否是bug,但向the Google issue tracker报告如何?不幸的是,我在当前的 Google 问题跟踪器中找不到这个问题。