HTML 服务:与服务器功能通信

google.script.run 是一个异步函数 客户端 JavaScript API,允许 HTML 服务页面调用服务器端的 Apps 脚本函数。以下示例展示了最基本的功能 /google.script.run - 在服务器上调用函数

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function doSomething() {
  Logger.log('I was called!');
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      google.script.run.doSomething();
    </script>
  </head>
</html>

如果将此脚本部署为 Web 应用并访问其网址,您将不会看到 但如果你查看日志,就会发现服务器正常运行 已调用 doSomething()

客户端调用服务器端函数是异步的:浏览器在 请求服务器运行 doSomething() 函数,浏览器会继续执行 直接添加到下一行代码,而不必等待响应。这意味着 服务器函数调用可能无法按您预期的顺序执行。如果您 因为无法知道哪个函数 先运行结果可能会因网页每次加载而有所不同在这种情况下 成功处理程序失败处理程序 有助于控制您的代码流。

google.script.run API 允许对服务器函数进行 10 个并发调用。如果 您进行第 11 次调用,而 10 次调用仍在运行时,则服务器函数 直到 10 个位置中的其中一个释放出来。在实际操作中 考虑到这一限制,特别是考虑到大多数浏览器已经 向同一服务器发出的并发请求数小于 10 例如,在 Firefox 中,上限为 6。大多数浏览器同样会延迟 服务器请求,直到某个现有请求完成为止。

参数和返回值

您可以从客户端使用参数调用服务器函数。同样, 服务器函数可以将值作为传递给 成功处理程序

合法参数和返回值是 JavaScript 原语,例如 NumberBooleanStringnull,以及 由基元、对象和数组组成。页面中的 form 元素 作为参数也是合法的,但必须是函数唯一的参数,并且 作为返回值并不合法。如果您尝试传递 DateFunctionform 或其他被禁止的类型之外的 DOM 元素; 包括对象或数组内禁止的类型。创建的对象 循环引用也会失败,数组中未定义的字段也会变为 null

请注意,传递给服务器的对象将成为原始对象的副本。如果 服务器函数接收对象并更改其属性, 因此客户不会受到影响

成功处理程序

因为客户端代码会继续执行下一行,而不必等待服务器 调用完成 withSuccessHandler(function) 您可以指定一个客户端回调函数,该函数要在服务器访问期间 响应。如果服务器函数返回一个值,则 API 会将该值传递给 将新函数作为参数传递。

以下示例会在服务器响应时显示浏览器提醒。注意事项 此代码示例需要授权,因为服务器端函数是 访问您的 Gmail 账号。对脚本进行授权的最简单方法是运行 getUnreadEmails() 函数,然后再执行此操作。 加载网页。或者,当您 部署 Web 应用时,您可以选择 以“访问 Web 应用的用户”的身份执行,在这种情况下, 会提示您进行授权。

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getUnreadEmails() {
  return GmailApp.getInboxUnreadCount();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess(numUnread) {
        var div = document.getElementById('output');
        div.innerHTML = 'You have ' + numUnread
            + ' unread messages in your Gmail inbox.';
      }

      google.script.run.withSuccessHandler(onSuccess)
          .getUnreadEmails();
    </script>
  </head>
  <body>
    <div id="output"></div>
  </body>
</html>

失败处理程序

如果服务器无法响应或抛出错误, withFailureHandler(function) 可让您使用 Error 对象(如果有)作为参数传递。

默认情况下,如果您没有指定失败处理程序,则系统会将失败情况记录到 JavaScript 控制台。如需替换此值,请调用 withFailureHandler(null) 或提供 一个不执行任何操作的失败处理程序

失败处理程序的语法与成功处理程序几乎完全相同,因为 示例。

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getUnreadEmails() {
  // 'got' instead of 'get' will throw an error.
  return GmailApp.gotInboxUnreadCount();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onFailure(error) {
        var div = document.getElementById('output');
        div.innerHTML = "ERROR: " + error.message;
      }

      google.script.run.withFailureHandler(onFailure)
          .getUnreadEmails();
    </script>
  </head>
  <body>
    <div id="output"></div>
  </body>
</html>

User 对象

您可以将同一个成功或失败处理程序重复用于多次调用 调用服务器 withUserObject(object) 指定一个对象,该对象将作为第二个参数传递给处理程序。 此“用户对象”—请勿与 User 类 - 可让您响应 客户端与服务器联系的上下文。由于用户对象不是 发送到服务器,它们几乎可以是任何内容,包括函数、DOM 元素等等,而无需限制参数和返回值 。但是,用户对象不能是使用 new 运算符。

在本例中,点击两个按钮中的任意一个会将该按钮更新为 值,同时让另一个按钮保持不变, 共享一个成功处理程序。在 onclick 处理程序内,关键字 this 是指 button 本身。

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getEmail() {
  return Session.getActiveUser().getEmail();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function updateButton(email, button) {
        button.value = 'Clicked by ' + email;
      }
    </script>
  </head>
  <body>
    <input type="button" value="Not Clicked"
      onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
    <input type="button" value="Not Clicked"
      onclick="google.script.run
          .withSuccessHandler(updateButton)
          .withUserObject(this)
          .getEmail()" />
  </body>
</html>

表单

如果您使用 form 元素作为参数来调用服务器函数,则表单 会变为单个对象,并以字段名称作为键,以字段值作为值。通过 值均转换为字符串,但 file-input 的内容除外 字段,这些字段将变为 Blob 对象。

此示例在不重新加载的情况下处理表单(包括文件输入字段) 该网页;它会将相应文件上传到 Google 云端硬盘,然后输出 位于客户端页面中。在 onsubmit 处理程序内,关键字 this 指的是表单本身。请注意,在加载页面中的所有表单时, 默认提交操作已被 preventFormSubmit 停用。这样可以防止 网页重定向到不准确的网址。

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function processForm(formObject) {
  var formBlob = formObject.myFile;
  var driveFile = DriveApp.createFile(formBlob);
  return driveFile.getUrl();
}

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      // Prevent forms from submitting.
      function preventFormSubmit() {
        var forms = document.querySelectorAll('form');
        for (var i = 0; i < forms.length; i++) {
          forms[i].addEventListener('submit', function(event) {
            event.preventDefault();
          });
        }
      }
      window.addEventListener('load', preventFormSubmit);

      function handleFormSubmit(formObject) {
        google.script.run.withSuccessHandler(updateUrl).processForm(formObject);
      }
      function updateUrl(url) {
        var div = document.getElementById('output');
        div.innerHTML = '<a href="' + url + '">Got it!</a>';
      }
    </script>
  </head>
  <body>
    <form id="myForm" onsubmit="handleFormSubmit(this)">
      <input name="myFile" type="file" />
      <input type="submit" value="Submit" />
    </form>
    <div id="output"></div>
 </body>
</html>

脚本运行程序

您可以将 google.script.run 视为“脚本运行程序”的构建器。如果您 向脚本运行程序添加成功处理程序、失败处理程序或用户对象, 不会更改现有运行程序;而是会返回一个新的脚本运行程序 新行为。

您可以使用 withSuccessHandler()withFailureHandler()withUserObject()。您还可以调用 在已设置值的脚本运行程序上修改函数。新的 只会覆盖之前的值

本示例为所有三个服务器调用设置了通用的失败处理程序, 单独的成功处理程序:

var myRunner = google.script.run.withFailureHandler(onFailure);
var myRunner1 = myRunner.withSuccessHandler(onSuccess);
var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess);

myRunner1.doSomething();
myRunner1.doSomethingElse();
myRunner2.doSomething();

私有函数

名称以下划线结尾的服务器函数被视为私有函数。 google.script 无法调用这些函数,它们的名称也永远不会改变 发送给客户端因此,您可以使用它们来隐藏 在服务器上需要保密。google.script也看不到 中的函数和 在脚本的顶层声明的。

在此示例中,函数 getBankBalance() 在客户端中可用 代码;即使 不要调用它不过,函数 deepSecret_()obj.objectMethod() 对 客户端。

Code.gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('Index');
}

function getBankBalance() {
  var email = Session.getActiveUser().getEmail()
  return deepSecret_(email);
}

function deepSecret_(email) {
 // Do some secret calculations
 return email + ' has $1,000,000 in the bank.';
}

var obj = {
  objectMethod: function() {
    // More secret calculations
  }
};

Index.html

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script>
      function onSuccess(balance) {
        var div = document.getElementById('output');
        div.innerHTML = balance;
      }

      google.script.run.withSuccessHandler(onSuccess)
          .getBankBalance();
    </script>
  </head>
  <body>
    <div id="output">No result yet...</div>
  </body>
</html>

调整应用中 Google Workspace 对话框的大小

Google 文档、表格或 Google 文档中的自定义对话框 通过调用 google.script.host 方法 setWidth(width)setHeight(height) 英寸 客户端代码中。(如需设置对话框的初始大小,请使用 HtmlOutput 种方式 setWidth(width)setHeight(height)。) 请注意,对话框在调整尺寸后不会将父窗口重新居中, 无法调整边栏的大小。

关闭“ Google Workspace”中的对话框和边栏

如果您使用 HTML 服务显示 对话框或边栏创建 Google 文档、表格或 表单,您无法通过调用 window.close() 关闭接口。相反, 必须调用 google.script.host.close()。 有关示例,请参见 提供 HTML 作为 Google Workspace 界面

将浏览器焦点移到 Google Workspace

要将用户浏览器中的焦点从对话框或边栏切换回 Google 文档、表格或表单编辑器,只需调用 google.script.host.editor.focus()。 此方法与 文档服务方法 Document.setCursor(position)Document.setSelection(range)