google.script.run
to asynchroniczny interfejs API JavaScript po stronie klienta, który umożliwia stronom usługi HTML wywoływanie funkcji Apps Script po stronie serwera. Poniższy przykład pokazuje najbardziej podstawową funkcję google.script.run
, czyli wywoływanie funkcji na serwerze z JavaScriptu po stronie klienta.
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>
Jeśli wdrożysz ten skrypt jako aplikację internetową i otworzysz jej adres URL, nic nie zobaczysz, ale jeśli wyświetlisz logi, zauważysz, że wywołana została funkcja serwera doSomething()
.
Wywołania funkcji po stronie serwera z poziomu klienta są asynchroniczne: po tym, jak przeglądarka zażąda od serwera uruchomienia funkcjidoSomething()
, od razu przechodzi do następnego wiersza kodu, nie czekając na odpowiedź. Oznacza to, że wywołania funkcji serwera mogą nie być wykonywane w oczekiwanej kolejności. Jeśli wykonasz 2 wywołania funkcji w tym samym czasie, nie będziesz mieć pewności, która z nich zostanie uruchomiona jako pierwsza. Wynik może się różnić przy każdym wczytaniu strony. W takiej sytuacji funkcje obsługi sukcesu i funkcje obsługi błędów
pomagają kontrolować przepływ kodu.
Interfejs google.script.run
API umożliwia 10 jednoczesnych wywołań funkcji serwera. Jeśli wykonasz 11 połączenie, gdy 10 połączeń jest nadal aktywnych, funkcja serwera zostanie opóźniona do momentu zwolnienia jednego z 10 miejsc. W praktyce rzadko musisz się martwić tym ograniczeniem, zwłaszcza że większość przeglądarek ogranicza już liczbę jednoczesnych żądań do tego samego serwera do wartości mniejszej niż 10.
Na przykład w Firefoxie limit wynosi 6. Większość przeglądarek podobnie opóźnia nadmiarowe żądania serwera, dopóki nie zostanie zrealizowane jedno z dotychczasowych żądań.
Parametry i wartości zwracane
Możesz wywołać funkcję serwera z parametrami klienta. Podobnie funkcja serwera może zwrócić wartość do klienta jako parametr przekazany do procedury obsługi sukcesu.
Prawidłowe parametry i wartości zwracane to podstawowe typy danych JavaScript, takie jak Number
, Boolean
, String
lub null
, a także obiekty i tablice JavaScript, które składają się z tych typów danych, obiektów i tablic. Element form
na stronie jest też prawidłowy jako parametr, ale musi być jedynym parametrem funkcji i nie jest prawidłowy jako wartość zwracana. Żądania kończą się niepowodzeniem, jeśli spróbujesz przekazać element Date
, Function
, DOM inny niż form
lub inny niedozwolony typ, w tym niedozwolone typy w obiektach lub tablicach. Obiekty, które tworzą odwołania cykliczne, również nie będą działać, a niezdefiniowane pola w tablicach staną się null
.
Pamiętaj, że obiekt przekazany na serwer staje się kopią oryginału. Jeśli funkcja serwera otrzyma obiekt i zmieni jego właściwości, nie wpłynie to na właściwości po stronie klienta.
Moduły obsługi powodzenia
Kod po stronie klienta przechodzi do następnego wiersza bez oczekiwania na zakończenie wywołania serwera. Funkcja withSuccessHandler(function)
umożliwia określenie funkcji wywołania zwrotnego po stronie klienta, która ma zostać uruchomiona, gdy serwer odpowie. Jeśli funkcja serwera zwraca wartość, interfejs API przekazuje ją do nowej funkcji jako parametr.
Poniższy przykład pokazuje alert przeglądarki, gdy serwer odpowiada. Uwaga: ten przykładowy kod wymaga autoryzacji, ponieważ funkcja po stronie serwera uzyskuje dostęp do Twojego konta Gmail. Najprostszym sposobem autoryzacji skryptu jest ręczne uruchomienie funkcji getUnreadEmails()
w edytorze skryptów raz przed załadowaniem strony. Możesz też wdrożyć aplikację internetową i wybrać, aby była wykonywana jako „użytkownik uzyskujący dostęp do aplikacji internetowej”. W takim przypadku podczas ładowania aplikacji pojawi się prośba o autoryzację.
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>
Moduły obsługi błędów
Jeśli serwer nie odpowie lub zgłosi błąd, funkcja
withFailureHandler(function)
umożliwia określenie procedury obsługi błędu zamiast procedury obsługi powodzenia, z obiektem
Error
(jeśli występuje) przekazywanym jako argument.
Domyślnie, jeśli nie określisz modułu obsługi błędów, błędy są rejestrowane w konsoli JavaScript. Aby to zmienić, wywołaj funkcję withFailureHandler(null)
lub podaj
funkcję obsługi błędów, która nic nie robi.
Składnia funkcji obsługi błędów jest niemal identyczna ze składnią funkcji obsługi powodzenia, co widać na tym przykładzie.
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>
Obiekty użytkownika
Możesz ponownie użyć tego samego modułu obsługi sukcesu lub błędu w przypadku wielu wywołań serwera, wywołując withUserObject(object)
, aby określić obiekt, który zostanie przekazany do modułu obsługi jako drugi parametr.
Ten „obiekt użytkownika” – nie należy go mylić z klasą User
– umożliwia odpowiadanie na kontekst, w którym klient skontaktował się z serwerem. Obiekty użytkownika nie są wysyłane na serwer, więc mogą być niemal dowolne, w tym funkcje, elementy DOM itp., bez ograniczeń dotyczących parametrów i wartości zwracanych w przypadku wywołań serwera. Obiekty użytkownika nie mogą jednak być obiektami utworzonymi za pomocą operatora new
.
W tym przykładzie kliknięcie dowolnego z 2 przycisków spowoduje zaktualizowanie tego przycisku o wartość z serwera, a drugi przycisk pozostanie bez zmian, mimo że oba przyciski mają ten sam moduł obsługi sukcesu. W funkcji obsługi onclick
słowo kluczowe this
odnosi się do samego 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>
Formularze
Jeśli wywołasz funkcję serwera z elementem form
jako parametrem, formularz stanie się pojedynczym obiektem, w którym nazwy pól będą kluczami, a wartości pól – wartościami. Wszystkie wartości są konwertowane na ciągi znaków, z wyjątkiem zawartości pól file-input, które stają się obiektami Blob
.
Ten przykład przetwarza formularz, w tym pole wprowadzania pliku, bez ponownego wczytywania strony. Przesyła plik na Dysk Google, a następnie drukuje adres URL pliku na stronie po stronie klienta. Wewnątrz funkcji obsługi onsubmit
słowo kluczowe this
odnosi się do samego formularza. Pamiętaj, że po wczytaniu wszystkich formularzy na stronie domyślna czynność przesyłania jest wyłączona przez preventFormSubmit
. Zapobiega to przekierowaniu strony do nieprawidłowego adresu URL w przypadku wystąpienia wyjątku.
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>
Uruchamiający skrypt
google.script.run
można traktować jako narzędzie do tworzenia „wykonawcy skryptów”. Jeśli dodasz do wykonawcy skryptów moduł obsługi sukcesu, moduł obsługi błędu lub obiekt użytkownika, nie zmienisz istniejącego wykonawcy. Zamiast tego otrzymasz nowego wykonawcę skryptów z nowym działaniem.
Możesz użyć dowolnej kombinacji i dowolnej kolejności atrybutów withSuccessHandler()
, withFailureHandler()
i withUserObject()
. Możesz też wywołać dowolną z funkcji modyfikujących w przypadku skryptu, który ma już ustawioną wartość. Nowa wartość po prostu zastępuje poprzednią.
W tym przykładzie ustawiono wspólny moduł obsługi błędów dla wszystkich 3 wywołań serwera, ale 2 osobne moduły obsługi sukcesu:
var myRunner = google.script.run.withFailureHandler(onFailure);
var myRunner1 = myRunner.withSuccessHandler(onSuccess);
var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess);
myRunner1.doSomething();
myRunner1.doSomethingElse();
myRunner2.doSomething();
Funkcje prywatne
Funkcje serwera, których nazwy kończą się podkreśleniem, są uważane za prywatne.
Funkcji tych nie można wywoływać za pomocą google.script
, a ich nazwy nigdy nie są wysyłane do klienta. Możesz ich więc używać do ukrywania szczegółów implementacji, które muszą pozostać tajne na serwerze. google.script
nie widzi też funkcji w bibliotekach ani funkcji, które nie są zadeklarowane na najwyższym poziomie skryptu.
W tym przykładzie funkcja getBankBalance()
jest dostępna w kodzie klienta. Użytkownik, który sprawdzi Twój kod źródłowy, może odkryć jej nazwę, nawet jeśli jej nie wywołasz. Funkcje deepSecret_()
i obj.objectMethod()
są jednak całkowicie niewidoczne dla klienta.
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>
Zmiana rozmiaru okien w aplikacjach Google Workspace
Niestandardowe okna dialogowe w Dokumentach, Arkuszach lub Formularzach Google można zmieniać, wywołując metody google.script.host
, setWidth(width)
lub setHeight(height)
w kodzie po stronie klienta. (Aby ustawić początkowy rozmiar okna, użyj metod HtmlOutput
methods
setWidth(width)
i
setHeight(height)
).
Pamiętaj, że po zmianie rozmiaru okna nie są ponownie wyśrodkowywane w oknie nadrzędnym i nie można zmieniać rozmiaru pasków bocznych.
Zamykanie okien i pasków bocznych w Google Workspace
Jeśli używasz usługi HTML do wyświetlania okna dialogowego lub paska bocznego w Dokumentach, Arkuszach lub Formularzach Google, nie możesz zamknąć interfejsu, wywołując window.close()
. Zamiast tego musisz wywołać funkcję google.script.host.close()
.
Przykład znajdziesz w sekcji wyświetlanie kodu HTML jako interfejsu użytkownika Google Workspace.
Przenoszenie fokusu przeglądarki w Google Workspace
Aby przełączyć fokus w przeglądarce użytkownika z okna dialogowego lub paska bocznego z powrotem na edytor Dokumentów, Arkuszy lub Formularzy Google, wystarczy wywołać metodę google.script.host.editor.focus()
.
Ta metoda jest szczególnie przydatna w połączeniu z metodami usługi Document:Document.setCursor(position)
i Document.setSelection(range)
.