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

8еа39680ц8 5138ц2ц823 800е90953а 1685бдфб67

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

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。大多数浏览器也会同样推迟多余的服务器请求,直到某个现有请求完成为止。

参数和返回值

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

合法参数和返回值采用 NumberBooleanStringnull 等 JavaScript 原语,以及由原语、对象和数组组成的 JavaScript 对象和数组。页面中的 form 元素 作为参数也是合法的,但必须是函数唯一的参数,并且 作为返回值并不合法。如果您尝试传递 form 以外的 DateFunction、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 文档、表格或 Google 文档中的自定义对话框 通过调用 google.script.host 方法 setWidth(width)setHeight(height) 英寸 客户端代码中。(如需设置对话框的初始大小,请使用 HtmlOutput 方法 setWidth(width)setHeight(height)。)请注意,对话框在调整大小后不会在父窗口中重新居中,并且无法调整边栏的大小。

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

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

将浏览器焦点移到

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