You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Apps Script中PropertiesService与客户端交互及计数器NaN问题排查

问题
  1. 如何将Google Apps Script中PropertiesService的字符串数据传递至客户端代码?
  2. 计数器属性如何从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();
}

问题分析与修复

核心问题点

  1. 服务器NaN错误:incrementCounter中getProperty(counter)的参数是未定义变量,需传入属性名字符串"counter"。
  2. 客户端counter为undefined:google.script.run是异步操作,直接赋值会得到undefined,必须在withSuccessHandler中处理返回值。
  3. DOM错误:代码尝试操作不存在的successfulClick元素,导致找不到节点报错。
  4. 初始化逻辑问题: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>

数据传递方法说明

  1. 初始数据传递:在doGet中通过模板变量将PropertiesService的值注入HTML,客户端用<?= initialCounter ?>直接获取。
  2. 异步交互传递:使用google.script.run调用服务器函数,通过withSuccessHandler接收返回的更新值,再同步到客户端UI。

内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:20:29