求助:将Google Apps Script异步onSuccess回调转换为Promise并使用await改造代码
解决异步回调导致的时序问题:改用Promise + await
我来帮你把这段基于回调的代码改成Promise+await的写法,彻底解决异步时序问题,让代码逻辑更清晰可靠,再也不会出现findData值错误或者延迟的情况。
第一步:封装Google Script调用为Promise
google.script.run本身是基于回调的API,我们先把它封装成Promise版本,这样就能用await来等待异步结果:
// 封装google.script.run为Promise,方便用async/await调用 function runGoogleScript(funcName, ...args) { return new Promise((resolve, reject) => { google.script.run .withSuccessHandler(resolve) // 成功时返回结果 .withFailureHandler(reject) // 失败时捕获错误(建议加上,方便调试) [funcName](...args); // 调用指定的后端函数并传参 }); }
第二步:改造keyPressFunction为异步函数
把原来的回调逻辑改成async/await,这样就能按顺序等待后端返回结果后再执行后续代码:
// 改成async函数,允许内部使用await async function keyPressFunction(ev) { const inputData = ev.target.value; if (ev.code !== 'Enter') return; const curInpID = ev.target.id; // 改成局部变量,减少全局污染 try { // 用await等待后端返回结果,直接拿到最新值 const findData = await runGoogleScript('searchData', inputData); console.log(findData); // 现在这里能正确获取到后端返回的布尔值了 // 处理表单焦点的逻辑(注意:确保formControl能正确获取到输入框元素) const formControl = document.querySelectorAll('.form-control'); for (const input of formControl) { if (input.value === '') { input.focus(); // 你原来写的nextElementSibling可能有误,这里调整为聚焦输入框本身 break; } } } catch (error) { // 捕获调用失败的情况,方便调试和给用户提示 console.error('调用后端searchData函数出错:', error); alert('验证失败,请检查输入或稍后重试'); } }
第三步:优化后端Apps Script的searchData函数
你的后端代码里有个小问题:login变量未定义,应该用传入的data参数,同时优化循环逻辑提升性能:
function searchData(data){ let firstValid = false; // 用for...of循环更简洁,找到匹配项后直接跳出循环 for (const login of arrLogins) { if (login.indexOf(data) !== -1) { firstValid = true; break; } } return firstValid; }
为什么这样改能解决问题?
- 异步时序问题:原来的
console.log(findData)在onSuccess回调执行前就运行了,所以拿到的是旧值或者undefined。用await后,代码会等待后端返回结果后再执行后续逻辑,确保拿到的是最新的正确值。 - 代码可读性:
async/await让异步代码看起来像同步代码,逻辑更清晰,避免了回调嵌套的混乱。 - 错误处理:新增的
try/catch能捕获后端调用失败的情况,方便调试和给用户友好提示。 - 减少全局变量:原来的全局
findData和curInpID改成局部变量,减少变量污染,避免意外的变量覆盖。
额外注意点
- 确保
formControl选择器能正确获取到所有输入框元素,我用了document.querySelectorAll('.form-control'),你可以根据实际DOM结构调整。 - 如果确实需要聚焦输入框的下一个兄弟元素,再把
input.focus()改回input.nextElementSibling.focus()即可。
内容的提问来源于stack exchange,提问作者Dmitriy Rudakov
相关产品推荐
相关产品推荐

