Serviço HTML: comunicar-se com as funções do servidor

google.script.run é uma interface assíncrona a API JavaScript do lado do cliente que permite que páginas de serviço HTML chamem o servidor funções do Apps Script. O exemplo a seguir mostra a funcionalidade mais básica de google.script.runchamar 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, não vai ver mas se você consultar os registros, vai perceber que a função do servidor doSomething() foi chamado.

As chamadas do lado do cliente para funções do lado do servidor são assíncronas: após o navegador solicitar que o servidor execute a função doSomething(), o navegador continuará imediatamente para a próxima linha de código sem esperar por uma resposta. Isso significa essas chamadas de função do servidor podem não ser executadas na ordem esperada. Se você fizer de duas funções ao mesmo tempo, não há como saber qual função executar primeiro; o resultado pode ser diferente cada vez que a página é carregada. Nessa situação, gerenciadores de sucesso e gerenciadores de 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 11a chamada enquanto outras 10 ainda estiverem em execução, a função do servidor será até que um dos 10 espaços seja liberado. Na prática, você raramente deve ter de pensar sobre essa restrição, especialmente porque a maioria dos navegadores já limita o número de solicitações simultâneas para o mesmo servidor com um número inferior a 10. No Firefox, por exemplo, o limite é 6. A maioria dos navegadores também atrasa o excesso solicitações do servidor até que uma das solicitações existentes seja concluída.

Parâmetros e valores de retorno

Você pode chamar uma função de servidor com parâmetros do cliente. Da mesma forma, uma função de servidor pode retornar um valor para o cliente como um parâmetro passado para um gerenciador de sucesso.

Parâmetros legais e valores de retorno são primitivos do JavaScript, como um Number. Boolean, String ou null, bem como as matrizes e objetos JavaScript que são compostas de primitivos, objetos e matrizes. um elemento form na página; também é legal como parâmetro, mas deve ser o único parâmetro da função e não é permitido como valor de retorno. As solicitações falharão se você tentar passar um Date, Function, um elemento DOM além de um form ou outro tipo proibido, incluindo tipos proibidos em objetos ou matrizes. Objetos que criam referências circulares também vão falhar, e campos indefinidos dentro das matrizes se tornarão null:

Observe que um objeto passado para o servidor se torna uma cópia do original. Se um do servidor recebe um objeto e altera suas propriedades, as propriedades do e o cliente não são afetados.

Gerenciadores de sucesso

Como o código do lado do cliente continua para a próxima linha sem esperar por um servidor chamada a ser concluída, withSuccessHandler(function) permite especificar uma função de callback do lado do cliente a ser executada quando o servidor responde. Se a função do servidor retornar um valor, a API o passará para a nova função como parâmetro.

O exemplo a seguir exibe um alerta do navegador quando o servidor responde. Observação que este exemplo de código requer autorização porque a função do lado do servidor é acessar 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, quando você implantar o app da Web, poderá escolher para executá-lo como o “usuário que acessa o web app”. Nesse caso, você será uma solicitação de autorização 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 falha

Caso o servidor não responda ou gere um erro, withFailureHandler(function) permite que você especifique um gerenciador de falhas em vez de um gerenciador de sucesso, com o Error objeto (se houver) passado como um argumento.

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 faz nada.

A sintaxe dos gerenciadores de falha é quase idêntica à dos gerenciadores de sucesso, já que esta 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

Você pode reutilizar o mesmo gerenciador de sucesso ou falha para diversas chamadas ao ao servidor chamando withUserObject(object) para especificar um objeto que será passado para o manipulador como um segundo parâmetro. Esse “objeto do usuário” não deve ser confundido com User: permite responder aos 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 quase qualquer coisa, inclusive funções, DOM elementos e assim por diante, sem as restrições de parâmetros e valores de retorno para chamadas de servidor. No entanto, os objetos de usuário não podem ser construídos com o Operador new.

Neste exemplo, clicar em um dos dois botões atualiza o botão com uma do servidor, deixando o outro botão inalterado, mesmo que eles e compartilhar um gerenciador de sucesso. No 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 de servidor com um elemento form como parâmetro, o formulário se torna um único objeto com nomes de campos como chaves e valores de campo como valores. A valores são todos convertidos em strings, exceto o conteúdo dos campos de entrada campos, que se tornam objetos Blob.

Este exemplo processa um formulário, incluindo um campo de entrada de arquivo, sem recarregar. da página. ele faz o upload do arquivo no Google Drive e imprime o URL da na página do cliente. No gerenciador onsubmit, a palavra-chave this refere-se 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 evita que redirecione o usuário 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 no google.script.run como um builder para um "executor de script". Se você adicionar um gerenciador de sucesso, gerenciador de falhas ou objeto de usuário a um executor de scripts, não estão mudando o executor atual. você recebe um novo executor de scripts, com um novo comportamento.

Você pode usar qualquer combinação e ordem de withSuccessHandler(), withFailureHandler() e withUserObject(). Você também pode chamar qualquer um modificar funções em um executor de scripts que já tenha um valor definido; A nova simplesmente substitui o valor 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 de servidor com nomes que terminam com um sublinhado são consideradas privadas. Essas funções não podem ser chamadas por google.script e os nomes delas nunca são enviados ao cliente. Assim, você pode usá-los para ocultar detalhes de implementação que precisam ser mantidos em sigilo no servidor. google.script também não consegue acessar em bibliotecas e funções que não são declarados no nível superior do script.

Neste exemplo, a função getBankBalance() está disponível no cliente código um usuário que inspecionar o código-fonte poderá descobrir o nome dele mesmo se 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>

Redimensionar caixas de diálogo em Google Workspace aplicativos

Caixas de diálogo personalizadas nos apps Documentos, Planilhas ou Os formulários podem ser redimensionados chamando o Métodos google.script.host setWidth(width) ou setHeight(height) pol. o código do lado do cliente. Para definir o tamanho inicial de uma caixa de diálogo, use o método HtmlOutput métodos setWidth(width) e setHeight(height)). As caixas de diálogo não são recentralizadas na janela principal quando redimensionadas não é possível redimensionar barras laterais.

Fechar caixas de diálogo e barras laterais no Google Workspace

Se você usar o serviço HTML para exibir uma caixa de diálogo ou barra lateral nos apps Documentos, Planilhas ou Formulários, não é possível fechar a interface chamando window.close(). Em vez disso, precisa ligar google.script.host.close() Para ver um exemplo, consulte a seção disponibilizar HTML como uma Google Workspace interface do usuário.

Mudando o foco do navegador em Google Workspace

Para mudar o foco no navegador do usuário de uma caixa de diálogo ou barra lateral de volta para a seção Editores dos apps Documentos, Planilhas ou Formulários Google, basta chamar o método google.script.host.editor.focus() Este método é particularmente útil em combinação com o Métodos do serviço de documentos Document.setCursor(position) e Document.setSelection(range).