google.script.run é uma API JavaScript assíncrona do lado do cliente que permite que as páginas do serviço HTML chamem funções do Apps Script do lado do servidor. O exemplo a seguir mostra a funcionalidade mais básica
de google.script.run — chamar uma função no
servidor do 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, nada será mostrado. No entanto, se você 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, o navegador 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 será possível saber qual função será executada primeiro. O resultado poderá ser diferente a cada vez que você carregar a página. Nessa situação,
os gerenciadores de sucesso e falha
ajudam a controlar o fluxo do código.
A API google.script.run permite 10 chamadas simultâneas para funções do servidor. Se você fizer uma 11ª chamada enquanto 10 ainda estiverem em execução, a função do servidor 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 para o mesmo servidor a um número menor que 10.
No Firefox, por exemplo, o limite é 6. A maioria dos navegadores também atrasa as solicitações de servidor em excesso até que uma das solicitações atuais seja concluída.
Parâmetros e valores de retorno
Chame uma função do servidor com parâmetros do cliente. Da mesma forma, uma função do servidor pode retornar um valor ao 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 de JavaScript que são compostos de primitivos, objetos e matrizes. Um elemento form na página também é legal como um parâmetro, mas precisa ser o único parâmetro da função e não é legal como um valor de retorno. As solicitações falham se você tentar transmitir um Date, Function, elemento DOM além de um form ou outro tipo proibido, incluindo tipos proibidos dentro de objetos ou matrizes. Objetos que criam referências circulares também falham, e campos indefinidos em matrizes se tornam null.
Um objeto transmitido ao servidor se torna uma cópia do original. Se uma função do servidor receber um objeto e mudar as propriedades dele, as propriedades no cliente não serão afetadas.
Gerenciadores de sucesso
Como as chamadas google.script.run são assíncronas, o código do lado do cliente continua para a próxima linha sem aguardar uma resposta. Para especificar uma função de callback que é executada quando o servidor responde, use
withSuccessHandler(function).
Se a função do servidor retornar um valor, a API transmitirá esse valor para a função de callback como um parâmetro.
O exemplo a seguir mostra um alerta do navegador quando o servidor responde. Esse exemplo de código requer autorização porque a função do lado do servidor acessa sua conta do Gmail. Para autorizar o script, execute a função getUnreadEmails manualmente no editor de scripts uma vez antes de carregar a página. Como alternativa, quando você
implanta o app da Web para
execução como o "usuário que acessa o app da Web", a autorização é solicitada
ao 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
Se o servidor não responder ou gerar um erro,
withFailureHandler(function)
permite que você especifique um gerenciador de falhas para ser executado no lugar de um gerenciador de sucesso.
Se ocorrer um erro, a API transmitirá o
Error
objeto como um argumento para o gerenciador de falhas.
Por padrão, se você não especificar um gerenciador de falhas, as falhas 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 falhas é quase idêntica aos gerenciadores de sucesso, como mostra este exemplo.
Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function getUnreadEmails() {
// 'got' instead of 'get' throws 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
Para reutilizar o mesmo gerenciador de sucesso ou falha para várias chamadas ao
servidor, chame
withUserObject(object)
para especificar um objeto transmitido ao gerenciador como um segundo parâmetro.
Esse "objeto do usuário", que não deve ser confundido com a
User classe, permite responder ao
contexto em que o cliente entrou em contato com o servidor. Como os objetos do usuário não são enviados ao servidor, eles podem ser a maioria das coisas, incluindo funções e elementos DOM, sem as restrições de parâmetros e valores de retorno para chamadas de servidor. Os objetos do usuário não podem ser objetos construídos com o operador new.
Neste exemplo, clicar em um dos dois botões atualiza esse botão com um valor do servidor, deixando o outro botão inalterado, mesmo que eles compartilhem um gerenciador de sucesso. Dentro do gerenciador onclick, a palavra-chave this se refere 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 um parâmetro, o formulário se tornará um único objeto com nomes de campo como chaves e valores de campo como valores. Os
valores são todos convertidos em strings, exceto o conteúdo dos campos de entrada de arquivos, que se tornam Blob objetos.
Este exemplo processa um formulário, incluindo um campo de entrada de arquivos, sem recarregar a página. Ele faz upload do arquivo para o Google Drive e imprime o URL do arquivo na página do lado do cliente. Dentro do gerenciador onsubmit, a palavra-chave this se refere ao próprio formulário. Ao carregar todos os formulários na página, a ação de envio padrão é desativada por preventFormSubmit. Isso impede que a página seja redirecionada para um URL impreciso em caso de 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 para um "executor de scripts". Se você adicionar um gerenciador de sucesso, um gerenciador de falhas ou um objeto do usuário a um executor de scripts, não estará mudando o executor atual. Em vez disso, você receberá um novo executor de scripts com um novo comportamento.
Use qualquer combinação e qualquer ordem de withSuccessHandler, withFailureHandler e withUserObject. Também chame qualquer uma das funções de modificação em um executor de scripts que já tenha um valor definido. O novo valor substitui o anterior.
Este exemplo define um gerenciador de falhas comum para todas as três chamadas de 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 particulares
As funções do servidor cujos nomes 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. É possível usá-las para ocultar detalhes de implementação que precisam ser mantidos em segredo no servidor. google.script também não pode ver
funções em bibliotecas ou funções não
declaradas no nível superior do script.
Neste exemplo, a função getBankBalance está disponível no código do cliente. Um usuário que inspeciona o código-fonte pode descobrir o nome dela, mesmo que você não a 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>Redimensionar caixas de diálogo nos aplicativos do Google Workspace
As caixas de diálogo personalizadas nos Documentos Google,
Planilhas Google ou Formulários podem ser redimensionadas chamando os
google.script.host métodos
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 HtmlOutput
métodos
setWidth(width)
e
setHeight(height).
As caixas de diálogo não são centralizadas novamente na janela pai quando redimensionadas, e
não é possível redimensionar as barras laterais.
Fechar caixas de diálogo e barras laterais no Google Workspace
Se você usar o serviço HTML para mostrar uma caixa de diálogo ou
barra lateral nos Documentos, Planilhas,
ou Formulários Google, não será possível fechar a interface chamando
window.close. Em vez disso, você precisa chamar
google.script.host.close.
Para conferir um exemplo, consulte a seção sobre como exibir HTML como uma interface do usuário do Google Workspace
user
interface.
Mover o foco do navegador no Google Workspace
Para mudar o foco no navegador do usuário de uma caixa de diálogo ou barra lateral de volta para o
editor dos Documentos, Planilhas ou Formulários Google, chame o
método
google.script.host.editor.focus.
Esse método é útil principalmente quando usado com os métodos do serviço Document Document.setCursor(position)
e
Document.setSelection(range).