google.script.run
ist eine asynchrone clientseitige JavaScript API, mit der serverseitige Apps Script-Funktionen von HTML-Dienstseiten aufgerufen werden können. Das folgende Beispiel zeigt die grundlegendste Funktion von google.script.run
: den Aufruf einer Funktion auf dem Server über clientseitiges 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>
Wenn Sie dieses Script als Webanwendung bereitstellen und die URL aufrufen, wird nichts angezeigt. In den Protokollen sehen Sie jedoch, dass die Serverfunktion doSomething()
aufgerufen wurde.
Clientseitige Aufrufe von serverseitigen Funktionen sind asynchron: Nachdem der Browser den Server aufgefordert hat, die Funktion doSomething()
auszuführen, fährt der Browser sofort mit der nächsten Codezeile fort, ohne auf eine Antwort zu warten. Das bedeutet, dass Serverfunktionsaufrufe möglicherweise nicht in der erwarteten Reihenfolge ausgeführt werden. Wenn Sie zwei Funktionsaufrufe gleichzeitig ausführen, lässt sich nicht vorhersagen, welche Funktion zuerst ausgeführt wird. Das Ergebnis kann sich jedes Mal unterscheiden, wenn Sie die Seite laden. In dieser Situation helfen Success-Handler und Failure-Handler, den Ablauf Ihres Codes zu steuern.
Die google.script.run
API ermöglicht zehn gleichzeitige Aufrufe von Serverfunktionen. Wenn Sie einen elften Aufruf starten, während zehn bereits ausgeführt werden, wird die Serverfunktion verzögert, bis einer der zehn Plätze frei ist. In der Praxis sollten Sie diese Einschränkung selten berücksichtigen müssen, zumal die meisten Browser die Anzahl der gleichzeitigen Anfragen an denselben Server bereits auf weniger als 10 beschränken.
In Firefox ist das Limit beispielsweise 6. Die meisten Browser verzögern überzählige Serveranfragen ebenfalls, bis eine der vorhandenen Anfragen abgeschlossen ist.
Parameter und Rückgabewerte
Sie können eine Serverfunktion mit Parametern vom Client aufrufen. Ebenso kann eine Serverfunktion einen Wert als Parameter an einen Success-Handler zurückgeben.
Zulässige Parameter und Rückgabewerte sind JavaScript-Primitivtypen wie Number
, Boolean
, String
oder null
sowie JavaScript-Objekte und ‑Arrays, die aus Primitivtypen, Objekten und Arrays bestehen. Ein form
-Element auf der Seite ist auch als Parameter zulässig, muss aber der einzige Parameter der Funktion sein. Als Rückgabewert ist es nicht zulässig. Anfragen schlagen fehl, wenn Sie versuchen, ein Date
-, Function
- oder DOM-Element außer einem form
oder einen anderen nicht zulässigen Typ zu übergeben, einschließlich nicht zulässiger Typen in Objekten oder Arrays. Objekte, die kreisförmige Verweise erstellen, schlagen ebenfalls fehl und nicht definierte Felder innerhalb von Arrays werden zu null
.
Hinweis: Ein an den Server übergebenes Objekt wird zu einer Kopie des Originals. Wenn eine Serverfunktion ein Objekt empfängt und seine Attribute ändert, sind die Attribute auf dem Client nicht betroffen.
Erfolgs-Handler
Da der clientseitige Code mit der nächsten Zeile fortfährt, ohne auf den Abschluss eines Serveraufrufs zu warten, können Sie mit withSuccessHandler(function)
eine clientseitige Callback-Funktion angeben, die ausgeführt wird, wenn der Server antwortet. Wenn die Serverfunktion einen Wert zurückgibt, übergibt die API den Wert als Parameter an die neue Funktion.
Im folgenden Beispiel wird eine Browserbenachrichtigung angezeigt, wenn der Server antwortet. Für dieses Codebeispiel ist eine Autorisierung erforderlich, da die serverseitige Funktion auf Ihr Gmail-Konto zugreift. Am einfachsten können Sie das Script autorisieren, indem Sie die Funktion getUnreadEmails()
einmal manuell im Script-Editor ausführen, bevor Sie die Seite laden. Alternativ können Sie beim Bereitstellen der Webanwendung festlegen, dass sie als „Nutzer, der auf die Webanwendung zugreift“ ausgeführt werden soll. In diesem Fall werden Sie beim Laden der App zur Autorisierung aufgefordert.
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>
Fehler-Handler
Falls der Server nicht antwortet oder einen Fehler zurückgibt, können Sie mit withFailureHandler(function)
einen Fehler-Handler anstelle eines Erfolgs-Handlers angeben. Das Error
-Objekt (falls vorhanden) wird als Argument übergeben.
Wenn Sie keinen Fehler-Handler angeben, werden Fehler standardmäßig in der JavaScript-Konsole protokolliert. Wenn du das überschreiben möchtest, rufe withFailureHandler(null)
auf oder gib einen Fehlerhandler an, der nichts tut.
Die Syntax für Fehler-Handler ist nahezu identisch mit der für Erfolgs-Handler, wie dieses Beispiel zeigt.
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>
Nutzerobjekte
Sie können denselben Erfolg- oder Fehler-Handler für mehrere Aufrufe des Servers wiederverwenden. Rufen Sie dazu withUserObject(object)
auf, um ein Objekt anzugeben, das als zweiter Parameter an den Handler übergeben wird.
Mit diesem „Nutzerobjekt“ – nicht zu verwechseln mit der Klasse User
– können Sie auf den Kontext antworten, in dem der Client den Server kontaktiert hat. Da Nutzerobjekte nicht an den Server gesendet werden, können sie fast alles sein, einschließlich Funktionen, DOM-Elemente usw., ohne die Einschränkungen für Parameter und Rückgabewerte für Serveraufrufe. Nutzerobjekte können jedoch nicht mit dem Operator new
erstellt werden.
In diesem Beispiel wird durch Klicken auf eine der beiden Schaltflächen diese Schaltfläche mit einem Wert vom Server aktualisiert, während die andere Schaltfläche unverändert bleibt, obwohl sie denselben Erfolgs-Handler teilen. Im onclick
-Handler bezieht sich das Keyword this
auf die button
selbst.
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>
Formulare
Wenn Sie eine Serverfunktion mit einem form
-Element als Parameter aufrufen, wird das Formular zu einem einzelnen Objekt mit Feldnamen als Schlüsseln und Feldwerten als Werten. Die Werte werden alle in Strings konvertiert, mit Ausnahme des Inhalts von Dateieingabefeldern, die zu Blob
-Objekten werden.
In diesem Beispiel wird ein Formular mit einem Dateieingabefeld verarbeitet, ohne die Seite neu zu laden. Die Datei wird in Google Drive hochgeladen und die URL für die Datei wird dann auf der clientseitigen Seite ausgegeben. Im onsubmit
-Handler bezieht sich das Keyword this
auf das Formular selbst. Beim Laden aller Formulare auf der Seite wird die standardmäßige Sendeaktion durch preventFormSubmit
deaktiviert. So wird verhindert, dass die Seite bei einer Ausnahme zu einer falschen URL weitergeleitet wird.
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>
Scriptausführer
Sie können sich google.script.run
als Builder für einen „Script Runner“ vorstellen. Wenn Sie einem Script Runner einen Erfolgs- oder Fehler-Handler oder ein Nutzerobjekt hinzufügen, ändern Sie den vorhandenen Runner nicht. Stattdessen erhalten Sie einen neuen Script Runner mit neuem Verhalten.
Sie können eine beliebige Kombination und Reihenfolge von withSuccessHandler()
, withFailureHandler()
und withUserObject()
verwenden. Sie können auch eine der Änderungsfunktionen für einen Script-Runner aufrufen, für den bereits ein Wert festgelegt wurde. Der neue Wert überschreibt einfach den vorherigen Wert.
In diesem Beispiel wird für alle drei Serveraufrufe ein gemeinsamer Fehler-Handler festgelegt, aber zwei separate Erfolgs-Handler:
var myRunner = google.script.run.withFailureHandler(onFailure);
var myRunner1 = myRunner.withSuccessHandler(onSuccess);
var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess);
myRunner1.doSomething();
myRunner1.doSomethingElse();
myRunner2.doSomething();
Private Funktionen
Serverfunktionen, deren Namen auf einen Unterstrich enden, gelten als privat.
Diese Funktionen können nicht von google.script
aufgerufen werden und ihre Namen werden nie an den Client gesendet. So können Sie Implementierungsdetails ausblenden, die auf dem Server geheim gehalten werden müssen. google.script
kann auch keine Funktionen in Bibliotheken und Funktionen sehen, die nicht auf der obersten Ebene des Scripts deklariert sind.
In diesem Beispiel ist die Funktion getBankBalance()
im Clientcode verfügbar. Ein Nutzer, der Ihren Quellcode untersucht, kann ihren Namen ermitteln, auch wenn Sie sie nicht aufrufen. Die Funktionen deepSecret_()
und obj.objectMethod()
sind jedoch für den Client vollständig unsichtbar.
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>
Größe von Dialogfeldern in Google Workspace Anwendungen anpassen
Die Größe der benutzerdefinierten Dialogfelder in Google Docs, Google Tabellen und Google Formulare kann durch Aufrufen der google.script.host
-Methoden setWidth(width)
oder setHeight(height)
im clientseitigen Code angepasst werden. Die anfängliche Größe eines Dialogfelds können Sie mit den HtmlOutput
-Methoden setWidth(width)
und setHeight(height)
festlegen. Beachten Sie, dass Dialogfelder beim Ändern der Größe nicht wieder im übergeordneten Fenster zentriert werden. Außerdem ist es nicht möglich, die Größe der Seitenleisten anzupassen.
Dialogfelder und Seitenleisten in Google Workspacewerden geschlossen
Wenn Sie den HTML-Dienst verwenden, um in Google Docs, Google Tabellen oder Google Formulare ein Dialogfeld oder eine Seitenleiste anzuzeigen, können Sie die Oberfläche nicht durch Aufrufen von window.close()
schließen. Stattdessen müssen Sie google.script.host.close()
aufrufen.
Ein Beispiel finden Sie im Abschnitt zum Ausliefern von HTML als Google Workspace Benutzeroberfläche.
Browserfokus in Google Workspaceverschieben
Wenn Sie den Fokus im Browser des Nutzers von einem Dialogfeld oder einer Seitenleiste zurück zum Editor von Google Docs, Google Tabellen oder Google Formulare wechseln möchten, rufen Sie einfach die Methode google.script.host.editor.focus()
auf.
Diese Methode ist besonders in Kombination mit den Document Service-Methoden Document.setCursor(position)
und Document.setSelection(range)
nützlich.