如何用Google Apps Script在侧边栏实时更新运行状态消息?
解决Google Apps Script实时显示运行进度的问题
核心问题原因
google.script.run采用单次请求-响应机制,服务器端函数只有执行完毕后才会将返回值传递给withSuccessHandler,无法在函数运行过程中主动向客户端推送中间状态。要实现实时进度展示,需采用客户端定时查询服务器端存储进度的方案。
可行实现方案
1. 服务器端:用PropertiesService存储进度,优化计算逻辑
通过PropertiesService存储当前进度与任务状态,拆分长任务为可追踪的结构,同时提供进度查询接口:
function computePO() { // 初始化进度与状态 const userProps = PropertiesService.getUserProperties(); userProps.setProperty('progress', '0'); userProps.setProperty('status', 'running'); const total = 10000; for (let i = 1; i <= total; i++) { // 替换为你的实际耗时业务逻辑 Utilities.sleep(1); // 每100次循环更新一次进度(减少存储操作频率,提升性能) if (i % 100 === 0) { const progressPercent = Math.round((i / total) * 100); userProps.setProperty('progress', `${progressPercent}%`); } } // 任务完成后更新状态 userProps.setProperty('progress', '100%'); userProps.setProperty('status', 'done'); return 'done'; } // 供客户端查询进度的接口函数 function getProgress() { const userProps = PropertiesService.getUserProperties(); return { progress: userProps.getProperty('progress') || '0', status: userProps.getProperty('status') || 'idle' }; }
2. 客户端:定时轮询进度,更新UI
在HTML侧边栏中,启动计算任务后通过setInterval定时查询进度,直到任务完成后停止轮询:
<!DOCTYPE html> <html> <body> <div id="msg">等待任务开始...</div> <button onclick="startCompute()">开始计算</button> <script> let pollInterval; function startCompute() { document.getElementById('msg').innerHTML = '任务启动中...'; // 启动服务器端计算任务 google.script.run .withSuccessHandler(() => { // 任务完成后清除轮询并更新提示 clearInterval(pollInterval); document.getElementById('msg').innerHTML = '任务完成!'; }) .withFailureHandler((err) => { // 出错时终止轮询并提示错误 clearInterval(pollInterval); document.getElementById('msg').innerHTML = `出错:${err.message}`; }) .computePO(); // 每500ms查询一次进度 pollInterval = setInterval(() => { google.script.run .withSuccessHandler(updateProgress) .getProgress(); }, 500); } function updateProgress(data) { if (data.status === 'running') { document.getElementById('msg').innerHTML = `当前进度:${data.progress}`; } } </script> </body> </html>
注意事项
- 轮询间隔不要小于300ms,避免触发GAS的调用频率限制
- 任务完成或出错后必须清除
setInterval,防止无效请求 - 多用户场景下必须使用
PropertiesService.getUserProperties()(每个用户独立存储进度),避免进度串号 - 可根据任务实际耗时调整进度更新的频率(示例中每100次循环更新一次,减少存储操作次数)
内容的提问来源于stack exchange,提问作者JoshL
相关产品推荐
相关产品推荐

