HTML 服務:與伺服器函式通訊

google.script.run 是非同步 可讓 HTML 服務頁面呼叫伺服器端的用戶端 JavaScript API Apps Script 函式。以下範例顯示最基本的功能 /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>

如果您是將這個指令碼部署為網頁應用程式,並造訪其網址,就不會 但如果您查看記錄檔,就會發現伺服器函數 已呼叫 doSomething()

用戶端函式的用戶端呼叫是以非同步的方式進行:在瀏覽器之後 要求伺服器執行 doSomething() 函式,瀏覽器繼續進行 不必等待回應。這表示伺服器函式呼叫可能不會依照您預期的順序執行。如果您同時發出兩個函式呼叫,就無法得知哪個函式會先執行;每次載入網頁時,結果可能會有所不同。在此情況下 成功處理常式失敗處理常式 有助於控製程式碼流程

google.script.run API 允許對伺服器函式並行 10 次呼叫。如果您在 10 個呼叫仍在執行時發出第 11 次呼叫,伺服器函式會延遲,直到 10 個位置中的其中一個釋出為止。實務上,您應該很少 考量這項限制,特別是因為大部分的瀏覽器都設有限制 對相同伺服器的並行要求數量低於 10。 舉例來說,Firefox 的限制為 6 個。大多數瀏覽器也同樣有延遲時間 伺服器傳送要求,直到現有的其中一個要求完成為止。

參數和傳回值

您可以從用戶端呼叫含有參數的伺服器函式。同樣地, 伺服器函數會將值傳回給用戶端,做為傳遞至 成功處理常式

法律參數和傳回值是 JavaScript 基元,例如 NumberBooleanStringnull,以及會用來處理 由基元、物件和陣列組成網頁中的 form 元素 也同樣合法,但必須是函式的唯一參數,且 不合法的回傳值如果您嘗試 DateFunction、DOM 元素以外的 form 或其他禁止類型。 包括物件或陣列中禁止的類型。建立的物件 循環參照也會失敗,而陣列中的未定義欄位會變成 null

請注意,傳遞至伺服器的物件會成為原始物件的副本。如果 伺服器函數接收物件並變更其屬性, 則不受影響。

成功處理常式

因為用戶端程式碼繼續顯示在下一行,無需等待伺服器 呼叫完成 withSuccessHandler(function)敬上 可讓您指定要在伺服器執行時執行的用戶端回呼函式 給予回應。如果伺服器函式傳回值,API 就會將該值傳送至 將新函式做為參數使用

以下範例會在伺服器回應時顯示瀏覽器快訊。注意事項 這個程式碼範例需要授權,因為伺服器端函式 登入您的 Gmail 帳戶。授權指令碼最簡單的方法就是執行 請在指令碼編輯器中手動執行 getUnreadEmails() 函式, 載入網頁。或者,您也可以在部署網路應用程式時,選擇以「使用者存取網路應用程式」的身份執行應用程式,這樣一來,您在載入應用程式時,系統就會提示您授權。

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 元素等,且不會受到伺服器呼叫的參數和傳回值限制。不過,User 物件不能是以 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 元素做為參數來呼叫伺服器函式,則表單形式為 會成為單一物件,並以欄位名稱做為鍵和欄位值。所有值都會轉換為字串,但檔案輸入欄位的內容會變成 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();

Private 函式

名稱結尾為底線的伺服器函式會視為不公開。 這些函式無法由 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.script.host 方法 setWidth(width)setHeight(height)。(如要設定對話方塊的初始大小,請使用 HtmlOutput 方法 setWidth(width)setHeight(height)。 請注意,調整大小後,對話方塊不會重新置中。 無法調整側欄大小。

關閉 Google Workspace中的對話方塊和側欄

如果您使用 HTML 服務來顯示 Google 文件、試算表或試算表的對話方塊或側欄 Google 表單無法藉由呼叫 window.close() 關閉介面。而是 必須呼叫。 google.script.host.close()。 如需範例,請參閱 以 Google Workspace 使用者介面提供 HTML。

正在將瀏覽器焦點移至「 Google Workspace」

如何將使用者瀏覽器的焦點從對話方塊或側欄切換回 Google 文件、試算表或表單編輯器,只要在 google.script.host.editor.focus()。 如果同時使用 文件服務方法 Document.setCursor(position)敬上 和 Document.setSelection(range)