如何实现SweetAlert取消按钮终止正在执行的脚本函数
实现原理
google.script.run发起的Google Apps Script服务端任务一旦启动,前端没有提供原生API可以直接强制中断运行中的进程,仅关闭SweetAlert弹窗只会销毁前端UI组件,完全不会影响后台已经在调度执行的脚本。要实现取消按钮终止后台执行的效果,需要采用协作式终止方案:前后端共享一个取消状态标记,后台脚本在执行过程中主动轮询检查标记状态,前端点击取消时更新标记值,后台检测到标记为取消时主动退出执行逻辑。
具体实现步骤
- 第一步:在Apps Script服务端编写状态管理工具函数,用脚本属性存储取消标记,实现前后端状态共享
// 以下代码写在Apps Script后端代码文件中 // 重置取消标记(每次任务启动前、结束后调用) function resetCancelFlag() { PropertiesService.getScriptProperties().setProperty('TASK_CANCELLED', 'false'); } // 标记任务为取消状态(前端点取消时调用) function markTaskCancelled() { PropertiesService.getScriptProperties().setProperty('TASK_CANCELLED', 'true'); } // 检查当前任务是否已被取消(后台逻辑执行中轮询调用) function isCancelled() { return PropertiesService.getScriptProperties().getProperty('TASK_CANCELLED') === 'true'; }
- 第二步:改造原有的
merge_Columns后台函数,在所有耗时节点插入取消检查,检测到取消信号时主动终止逻辑
// 改造后的列合并函数示例 function merge_Columns() { try { // 任务启动前先重置取消标记 resetCancelFlag(); const sheet = SpreadsheetApp.getActiveSheet(); const totalColumns = sheet.getLastColumn(); // 替换为你原有的列遍历/处理逻辑 for (let col = 1; col <= totalColumns; col++) { // 每处理一列前检查一次取消状态 if (isCancelled()) { return { code: -1, msg: '操作已被用户终止' }; } // 此处写入你原有的同表头列合并逻辑 // ... } return { code: 0, msg: '同表头列合并完成' }; } catch (err) { return { code: 1, msg: `执行出错:${err.message}` }; } finally { // 无论任务成功/失败/取消,结束后都重置标记,避免影响下次执行 resetCancelFlag(); } }
注意:检查点的密度根据你的逻辑调整即可,一般每处理1列/每处理100行数据检查一次,密度过高会增加属性读写的性能开销,密度过低会导致取消操作响应延迟。
- 第三步:改造前端代码,给SweetAlert的取消按钮绑定事件,点击取消时触发后端标记更新
<button class="button-68" role="button" onclick="morphf3994()">Unir columnas con el mismo encabezado</button> <script> function morphf3994() { showLoadingSwal(); google.script.run .withSuccessHandler((res) => { Swal.close(); if (res.code === -1) { Swal.fire('已终止', res.msg, 'info'); return; } if (res.code === 1) { Swal.fire('执行失败', res.msg, 'error'); return; } Swal.fire('执行成功', res.msg, 'success'); }) .withFailureHandler((err) => { Swal.close(); Swal.fire('执行异常', err.message, 'error'); }) .merge_Columns(); } function showLoadingSwal() { Swal.fire({ titleText: "Ejecutando...", text: 'Por favor, no toques ni cierres el documento.', icon: 'warning', allowOutsideClick: false, showLoaderOnConfirm: true, showConfirmButton: false, showCancelButton: true, cancelButtonText: '终止执行', didOpen: () => { Swal.showLoading(); // 绑定取消按钮点击事件 const cancelBtn = Swal.getCancelButton(); cancelBtn.onclick = () => { // 点击后先调用后端接口标记取消 google.script.run.markTaskCancelled(); // 禁用按钮避免重复点击 cancelBtn.disabled = true; cancelBtn.innerText = '正在终止...'; } } }) } </script>
注意事项
- 该方案为协作式终止,只有代码运行到你添加的
isCancelled()检查点时才会退出,无法做到点击取消立刻强制杀死进程,这是Apps Script本身的平台限制,没有其他绕过方式。 - 如果你的
merge_Columns里存在无法拆分的长耗时单次操作(比如单次写入超大量数据、单次数十秒的接口请求),需要把长任务拆成多步小批量操作,才能插入检查点实现取消响应。 - 如果是多用户同时使用的插件,建议给每次触发的任务生成唯一ID,将取消标记按任务ID存储在用户属性中,避免不同用户的操作互相干扰。
内容的提问来源于stack exchange,提问作者user19389364
相关产品推荐
相关产品推荐

