google.script.run
é uma API JavaScript assíncrona do lado do cliente que permite que páginas de serviços HTML chamem funções do Apps Script no lado do servidor. O exemplo a seguir mostra a funcionalidade mais básica
de google.script.run
:
como chamar uma função no servidor
usando o JavaScript do lado do cliente.
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>
Se você implantar esse script como um app da Web e acessar o URL dele, não verá nada, mas, se visualizar os registros, verá que a função do servidor doSomething()
foi chamada.
As chamadas do lado do cliente para funções do lado do servidor são assíncronas: depois que o navegador
solicita que o servidor execute a função doSomething()
, ele continua
imediatamente para a próxima linha de código sem aguardar uma resposta. Isso significa
que as chamadas de função do servidor podem não ser executadas na ordem esperada. Se você fizer
duas chamadas de função ao mesmo tempo, não há como saber qual função será
executada primeiro. O resultado pode ser diferente sempre que você carregar a página. Nessa situação, os
gerenciadores de sucesso e os gerenciadores de falha
ajudam a controlar o fluxo do código.
A API google.script.run
permite 10 chamadas simultâneas para funções de servidor. Se
você fizer uma 11a chamada enquanto 10 ainda estiverem em execução, a função do servidor vai ser
atrasada até que um dos 10 locais seja liberado. Na prática, é raramente necessário pensar nessa restrição, especialmente porque a maioria dos navegadores já limita o número de solicitações simultâneas ao mesmo servidor com um número menor que 10.
No Firefox, por exemplo, o limite é seis. Da mesma forma, a maioria dos navegadores atrasa o excesso
de solicitações do servidor até que uma das solicitações existentes seja concluída.
Parâmetros e valores de retorno
É possível chamar uma função de servidor com parâmetros do cliente. Da mesma forma, uma função do servidor pode retornar um valor para o cliente como um parâmetro transmitido a um gerenciador de sucesso.
Parâmetros legais e valores de retorno são primitivos do JavaScript como Number
, Boolean
, String
ou null
, além de objetos e matrizes do JavaScript que são compostos de primitivos, objetos e matrizes. Um elemento form
na página
também é legal como parâmetro, mas precisa ser o único parâmetro da função e
não é legal como um valor de retorno. As solicitações vão falhar se você tentar transmitir um elemento
Date
, Function
, DOM além de um form
ou outro tipo proibido,
incluindo tipos proibidos em objetos ou matrizes. Os objetos que criam
referências circulares também vão falhar, e os campos indefinidos nas matrizes vão se tornar
null
.
Um objeto transmitido ao servidor se torna uma cópia do original. Se uma função do servidor receber um objeto e alterar as propriedades, as propriedades no cliente não serão afetadas.
Gerenciadores de sucesso
Como o código do lado do cliente continua para a próxima linha sem aguardar a conclusão
de uma chamada do servidor,
withSuccessHandler(function)
permite que você especifique uma função de callback do lado do cliente a ser executada quando o servidor
responder. Se a função do servidor retornar um valor, a API transmitirá o valor para
a nova função como um parâmetro.
O exemplo a seguir exibe um alerta do navegador quando o servidor responde. Esse exemplo de código requer autorização porque a função do lado do servidor está acessando sua conta do Gmail. A maneira mais simples de autorizar o script é executar
a função getUnreadEmails()
manualmente no editor de script uma vez antes de
carregar a página. Como alternativa, ao
implantar o app da Web, é possível executá-lo
como o "usuário que acessa o app da Web". Nesse caso, você vai precisar
pedir autorização quando carregar o app.
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>
Gerenciadores de falhas
Caso o servidor não responda ou gere um erro,
withFailureHandler(function)
permitirá que você especifique um gerenciador de falhas em vez de um gerenciador de sucesso, com o objeto
Error
(se houver) transmitido como um argumento.
Por padrão, se você não especificar um gerenciador de falhas, elas serão registradas no Console JavaScript. Para substituir isso, chame withFailureHandler(null)
ou forneça
um gerenciador de falhas que não faça nada.
A sintaxe dos gerenciadores de falha é quase idêntica aos gerenciadores de sucesso, como mostrado neste exemplo.
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>
Objetos do usuário
É possível reutilizar o mesmo gerenciador de sucesso ou falha para várias chamadas para o servidor chamando withUserObject(object)
para especificar um objeto que será transmitido para o gerenciador como um segundo parâmetro.
Esse "objeto de usuário" não deve ser confundido com a classe
User
: permite responder ao
contexto em que o cliente entrou em contato com o servidor. Como os objetos de usuário não são
enviados ao servidor, eles podem ser quase tudo, incluindo funções, elementos DOM
e assim por diante, sem restrições de parâmetros e valores de retorno
para chamadas do servidor. No entanto, objetos de usuário não podem ser objetos construídos com o
operador new
.
Neste exemplo, clicar em um dos dois botões atualizará o botão com um
valor do servidor, deixando o outro inalterado, mesmo que eles
compartilhem um gerenciador de sucesso. Dentro do gerenciador onclick
, a palavra-chave this
refere-se ao próprio 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>
Formulários
Se você chamar uma função do servidor com um elemento form
como parâmetro, o formulário
se tornará um único objeto com nomes de campos como chaves e valores de campo como valores. Os
valores são convertidos em strings, exceto o conteúdo dos campos de entrada
de arquivos, que se tornam objetos Blob
.
O exemplo processa um formulário, incluindo um campo de entrada de arquivo, sem recarregar a página. Ele faz upload do arquivo no Google Drive e imprime o URL do arquivo na página do lado do cliente. Dentro do gerenciador onsubmit
, a palavra-chave this
refere-se ao próprio formulário. Observe que, ao carregar todos os formulários da página, a ação de envio padrão é desativada pelo preventFormSubmit
. Isso impede que a
página seja redirecionada para um URL incorreto no caso de uma exceção.
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>
Executores de scripts
Pense em google.script.run
como um builder de um "executor de scripts". Se você
adicionar um gerenciador de sucesso, gerenciador de falhas ou objeto de usuário a um executor de scripts,
não vai mudar o executor existente. Em vez disso, receberá um novo executor de scripts
com novo comportamento.
É possível usar qualquer combinação e qualquer ordem de withSuccessHandler()
,
withFailureHandler()
e withUserObject()
. Também é possível chamar qualquer uma das
funções de modificação em um executor de script que já tenha um valor definido. O novo
valor simplesmente substitui o anterior.
Este exemplo define um gerenciador de falhas comum para as três chamadas do servidor, mas dois gerenciadores de sucesso separados:
var myRunner = google.script.run.withFailureHandler(onFailure);
var myRunner1 = myRunner.withSuccessHandler(onSuccess);
var myRunner2 = myRunner.withSuccessHandler(onDifferentSuccess);
myRunner1.doSomething();
myRunner1.doSomethingElse();
myRunner2.doSomething();
Funções privadas
As funções do servidor com nomes que terminam com um sublinhado são consideradas particulares.
Essas funções não podem ser chamadas por google.script
e os nomes delas nunca são
enviados ao cliente. Assim, eles podem ser usados para ocultar detalhes de implementação que precisam ser mantidos em sigilo no servidor. google.script
também não consegue ver
funções dentro de bibliotecas e funções que não são
declaradas no nível superior do script.
Neste exemplo, a função getBankBalance()
está disponível no código
cliente. Um usuário que inspeciona seu código-fonte pode descobrir o nome dele, mesmo que você
não o chame. No entanto, as funções deepSecret_()
e obj.objectMethod()
são completamente invisíveis para
o cliente.
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>
Redimensionamento de caixas de diálogo em Google Workspace aplicativos
Para redimensionar caixas de diálogo personalizadas nos apps Documentos, Planilhas ou Formulários Google, chame os métodos google.script.host
setWidth(width)
ou setHeight(height)
no código do lado do cliente. Para definir o tamanho inicial de uma caixa de diálogo, use os métodos
HtmlOutput
setWidth(width)
e
setHeight(height)
.
As caixas de diálogo não são recentralizadas na janela mãe quando redimensionadas.
Não é possível redimensionar as barras laterais.
Fechando caixas de diálogo e barras laterais em Google Workspace
Se você usa o serviço HTML para exibir uma
caixa de diálogo ou barra lateral no Documentos, Planilhas ou
Formulários Google, não é possível fechar a interface chamando window.close()
. Em vez disso, chame
google.script.host.close()
.
Por exemplo, consulte a seção sobre
como veicular HTML como uma Google Workspace interface do usuário.
Movendo o foco do navegador para Google Workspace
Para mudar o foco no navegador do usuário de uma caixa de diálogo ou barra lateral para o
editor do Documentos, Planilhas ou Formulários Google, basta chamar o método
google.script.host.editor.focus()
.
Esse método é particularmente útil em combinação com os métodos
serviço de documentos
Document.setCursor(position)
e
Document.setSelection(range)
.