Google Apps Script中PropertiesService与客户端交互及计数器NaN问题排查
问题
- 如何将Google Apps Script中PropertiesService的字符串数据传递至客户端代码?
- 计数器属性如何从PropertiesService读取、递增后写回?当前服务器日志显示计数器为NaN,客户端日志出现counter值为undefined及「Cannot set properties of null (setting 'innerHTML')」的DOM错误,相关信息如下:
服务器日志
increment incrementCounter Web App Oct 16, 2022, 4:20:11 PM 0.224 s Completed Cloud logs Oct 16, 2022, 4:20:11 PM Info NaN
客户端日志
addNote.. userCodeAppPanel:12 undefined userCodeAppPanel:13 jkljkljkl;jkl;jklj 2849282381-warden_bin_i18n_warden.js:105 Net state changed from IDLE to BUSY 2849282381-warden_bin_i18n_warden.js:105 Net state changed from BUSY to IDLE userCodeAppPanel:9 Uncaught TypeError: Cannot set properties of null (setting 'innerHTML') at userCodeAppPanel:9:62 at Lf (445342555-mae_html_user_bin_i18n_mae_html_user.js:92:266) at 445342555-mae_html_user_bin_i18n_mae_html_user.js:25:132 at Ug.V (445342555-mae_html_user_bin_i18n_mae_html_user.js:125:380) at Id (445342555-mae_html_user_bin_i18n_mae_html_user.js:56:477) at a (445342555-mae_html_user_bin_i18n_mae_html_user.js:54:52) (anonymous) @ userCodeAppPanel:9 Lf @ 445342555-mae_html_user_bin_i18n_mae_html_user.js:92 (anonymous) @ 445342555-mae_html_user_bin_i18n_mae_html_user.js:25 Ug.V @ 445342555-mae_html_user_bin_i18n_mae_html_user.js:125 Id @ 445342555-mae_html_user_bin_i18n_mae_html_user.js:56 a @ 445342555-mae_html_user_bin_i18n_mae_html_user.js:54
HTML代码
<!DOCTYPE html> <html> <head> <base target="_top"> <script> var counter = "65456456456456456456"; var note = ""; function addNote() { console.log("addNote.."); note = document.getElementById("note").value; counter = google.script.run.withSuccessHandler((success) => { document.getElementById("successfulClick").innerHTML = success; }) .incrementCounter(); console.log(counter); console.log(note); document.getElementById("counter").textContent = counter; document.getElementById("note").textContent = note; } </script> </head> <body> <div id="success"></div> <br> <div id="counter"></div> <br> <div id="row"></div> <br> <br> <br> <br> <br> <br> <br> <input type="textarea" cols="40" rows="5" id="note" value=""/> <input type="button" value="addNote" onclick="addNote()" /> </body> </html>
服务器端代码
function init() { PropertiesService.getScriptProperties().deleteAllProperties(); PropertiesService.getScriptProperties().setProperty("counter","3"); } function incrementCounter() { var counter = PropertiesService.getScriptProperties().getProperty(counter); counter = parseInt(counter); counter++; PropertiesService.getScriptProperties().setProperty("counter",counter); Logger.log(counter); return counter; } function getUrl() { Logger.log("getUrl.."); var url = ScriptApp.getService().getUrl(); return url; } function doGet(e) { // Logger.log("doGet.."); init(); var htmlOutput = HtmlService.createTemplateFromFile('WebApp'); htmlOutput.url = getUrl(); return htmlOutput.evaluate(); }
问题分析与修复
核心问题点
- 服务器NaN错误:
incrementCounter中getProperty(counter)的参数是未定义变量,需传入属性名字符串"counter"。 - 客户端counter为undefined:
google.script.run是异步操作,直接赋值会得到undefined,必须在withSuccessHandler中处理返回值。 - DOM错误:代码尝试操作不存在的
successfulClick元素,导致找不到节点报错。 - 初始化逻辑问题:
doGet每次调用init()会重置计数器为3,不符合递增需求。
修复后的代码
服务器端代码
function init() { // 仅在无counter属性时初始化,避免每次刷新重置 const props = PropertiesService.getScriptProperties(); if (!props.getProperty("counter")) { props.setProperty("counter", "3"); } } function incrementCounter() { const props = PropertiesService.getScriptProperties(); // 传入正确的属性名字符串 let counter = props.getProperty("counter"); // 转换数字时设置默认值,防止转换失败 counter = parseInt(counter) || 0; counter++; props.setProperty("counter", counter.toString()); Logger.log(counter); return counter; } function getUrl() { Logger.log("getUrl.."); return ScriptApp.getService().getUrl(); } function doGet(e) { init(); const htmlOutput = HtmlService.createTemplateFromFile('WebApp'); htmlOutput.url = getUrl(); // 将初始计数器值传递给模板 htmlOutput.initialCounter = PropertiesService.getScriptProperties().getProperty("counter"); return htmlOutput.evaluate(); }
HTML代码(WebApp.html)
<!DOCTYPE html> <html> <head> <base target="_top"> <script> // 从模板接收初始计数器值 var counter = <?= initialCounter ?>; var note = ""; function addNote() { console.log("addNote.."); note = document.getElementById("note").value; // 异步调用服务器函数,在成功回调中更新UI google.script.run.withSuccessHandler((updatedCounter) => { counter = updatedCounter; document.getElementById("counter").textContent = counter; // 使用存在的success元素显示更新信息 document.getElementById("success").innerHTML = "计数器已更新: " + counter; }).incrementCounter(); console.log(note); // 新增noteDisplay元素展示输入内容(input元素用value而非textContent) document.getElementById("noteDisplay").textContent = note; } </script> </head> <body> <div id="success"></div> <br> <div id="counter"></div> <br> <div id="noteDisplay"></div> <br> <div id="row"></div> <br> <br> <br> <br> <br> <br> <br> <input type="textarea" cols="40" rows="5" id="note" value=""/> <input type="button" value="addNote" onclick="addNote()" /> </body> </html>
数据传递方法说明
- 初始数据传递:在
doGet中通过模板变量将PropertiesService的值注入HTML,客户端用<?= initialCounter ?>直接获取。 - 异步交互传递:使用
google.script.run调用服务器函数,通过withSuccessHandler接收返回的更新值,再同步到客户端UI。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

