Com certeza você já ouvir falar sobre GlideAjax, mas talvez nunca tenha usado e tenha dúvidas sobre sua funcionalidade. Este artigo vamos falar e demonstrar como esse ótimo recurso pode ser utilizado!
O que é o GlideAjax?
O GlideAjax é uma biblioteca que permite que uma chamada feita no lado do cliente (client-side), como por exemplo um Client Script, um UI Policy etc, que pode invocar um uma função que está no lado do servidor (server-side), geralmente sendo um Script Include.
Resumo da ópera, é um Client Script chamando um ServerSide script, para obter uma informação que não está disponível para o Client Script.
Esta chamada pode ser síncrona ou assíncrona. E qual a diferença?
Numa chamada síncrona, a tela que realiza a chamada fica travada enquanto aquela solicitação está em andamento, muitas vezes dando a impressão que a tela “travou”. A ServiceNow não recomenda o uso de chamadas síncronas justamente por penalizar a experiência do usuário.
Já na chamada assíncrona, a navegação continua mais fluida e assim que a chamada tiver um resultado, uma função de callback será disparada, permitindo assim que você trate o resultado da forma necessária.
Sobre estas duas formas de chamada, vamos descrevê-las a seguir.
Client Side
É a parte do código que precisa da informação do back-end. Nesta parte vamos declarar o objeto GlideAjax, definir seus parâmetros, realizar a chamada, receber a resposta e terminar a operação.
Conforme citei antes, esta chamada pode ser síncrona ou assíncrona. Vamos ver como cada uma funciona.
Síncrona
Como o próprio nome diz, uma chamada síncrona irá executar as instruções do script de forma sequencial. Assim, cada linha será executada somente após o término da anterior.
Observação. A chamada síncrona não é suportada em aplicações escopadas.
// Declaração do objeto GlideAjax var ga = new GlideAjax('MeuScriptInclude'); // Definição do método a ser invocado ga.addParam('sysparm_name', 'NomeDoMetodo'); // Definição de parâmetros adicionais para o método desejado. ga.addParam('sysparm_nomeDoParametro', valorDoParametro); // O script aguardará o retorno da chamada para executar a próxima instrução. ga.getXMLWait(); // Gravamos o retorno da chamada na variavel resposta. var resposta = ga.getAnswer(); // Exibe um alerta da resposta alert(resposta);
Portanto a linha 12 só será executada após todas as anteriores serem finalizadas.
Assíncrona #1
Na versão assíncrona, a sessão não ficará presa enquanto a chamada Ajax é processada.
Então considere o seguinte snippet:
// Declaração do objeto GlideAjax var ga = new GlideAjax('MeuScriptInclude'); // Definição do método a ser invocado ga.addParam('sysparm_name', 'NomeDoMetodo'); // Definição de parâmetros adicionais para o método desejado. ga.addParam('sysparm_nomeDoParametro', valorDoParametro); // Aqui definimos qual função será chamada quando a resposta do Ajax estiver pronta. ga.getXML(meuCallback); alert('Aqui'); function meuCallback(response) { // Este é o comando para recuperar o retorno de uma chamada Ajax padrão var answer = response.responseXML.documentElement.getAttribute("answer"); alert('Acolá'); }
Como neste script definimos que a função “meuCallback” será chamada somente quando o retorno do processamento chegar, temos que o alerta da linha 9 será exibido logo após a chamada Ajax e nada mais acontecerá.
Alguns segundos depois (dependendo do tempo de processamento da sua função) será exibida a mensagem “Acolá”, mostrando que a chamada Ajax terminou. Legal Né ?
Assíncrona #2
Uma segunda versão de assíncrona está disponível, que é equivalente à anterior, que tem algumas opções a mais.
// Declaração do objeto GlideAjax var ga = new GlideAjax('MeuScriptInclude'); // Definição do método a ser invocado ga.addParam('sysparm_name', 'NomeDoMetodo'); // Definição de parâmetros adicionais para o método desejado. ga.addParam('sysparm_nomeDoParametro', valorDoParametro); // Aqui definimos qual função será chamada quando a resposta do Ajax estiver pronta. ga.getXMLAnswer(meuOutroCallback, null, valorDoParametro); alert('Aqui'); // Minha função de callback, que agora recebeu como outro parâmetro a variavel sysid function meuOutroCallback(answer, sysid) { // Aqui o answer já vem com a resposta pronta, não é necessário processar a resposta utilizando // o comando response.responseXML.documentElement.getAttribute("answer"); alert(answer); }
Como você pode ver, esta versão permite passar parâmetros adicionais para o callback, assim como já disponibiliza a reposta direto no primeiro argumento.
Vale a pena lembrar que também é possível omitir o segundo e terceiro parâmetros no método getXMLAnswer, fazendo com que ele fique exatamente igual ao exemplo anterior:
// Chamada utilizando getXMLAnswer, mas passando somente o nome da função de callback ga.getXMLAnswer(meuOutroCallbackDiferente); // A função de callback recebendo apenas 1 parâmetro, que é a resposta da chamada! function meuOutroCallbackDiferente(answer) { // A resposta já está na variavel answer. Só usar :) alert(answer); }
Server Side
Nesta parte fica o código que será chamado pelo cliente. Você pode criar seu próprio Script Include ou utilizar um já existente. O único pré-requisito é que este script esteja com a flag the Client Callable ligada!
Quando você liga esta flag, o próprio ServiceNow fará com que sua classe estenda a classe AbstractAjaxProcessor, que é necessária para que ela funcione com GlideAjax.
Assim é o código de um Script Include novo sem a flag:
var MeuScriptInclude = Class.create(); MeuScriptInclude.prototype = { initialize: function() { }, type: 'MeuScriptInclude' };
Após ligar a flag de “Client Callable“:
var MeuScriptInclude = Class.create(); MeuScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, { type: 'MeuScriptInclude' });
Perceba que na linha 2, o seu script passa a estender a classe AbstractAjaxProcessor e outro detalhe importantíssimo é que a função “initialize” é removida. E por quê?
Como sua classe passou a estender outra classe, a sua função “initialize” caso exista, irá sobrepor a função “initialize” da classe pai, no caso a AbstractAjaxProcessor! E caso você faça isso você tem grandes chances de quebrar a iniciação correta da classe pai, quebrando todo o código Ajax.
Portanto este deve ser o seu código inicial para um Script Include que suporte chamadas Ajax:

var MeuScriptInclude = Class.create(); MeuScriptInclude.prototype = Object.extendsObject(AbstractAjaxProcessor, { // Nome da função. NomeDoMetodo: function() { // Recebendo os parâmetros passados na chamada. var meuParametro = this.getParameter("sysparm_nomeDoParametro"); // Retornando resultado return (meuParametro == "Brasil") ? ' É TETRA!' : 'Fomos surpreendidos...' ; } type: 'MeuScriptInclude' });
Vamos ver o que aconteceu ali.
Na linha 5 definimos nossa função sem parâmetros.
Você deve estar se perguntando “Mas eu estou passando parâmetros!”. Calma pequeno Padawan!
Em chamadas Ajax, os parâmetros são recuperados de outra forma, não através da assinatura do método. Então sempre os métodos para Ajax não receberão argumentos!
Já na linha 7 temos a forma correta de ler os parâmetros passados na chamada. Outra regrinha:
Todos os parâmetros devem começar com “sysparm_”. Você pode enviar/ler quantos parâmetros forem necessários, desde que eles tenham nomes únicos e que todos comecem com sysparm_*.
No nosso exemplo, eu guardo o valor na variável “meuParametro”. E só para finalizar eu comparo o valor recebido com a string “Brasil”. Se forem iguais, eu devolvo um texto “É TETRA!”, caso contrário, retorno “Fomos surpreendidos…” 🙂
Segue abaixo um cheat-sheet para Ajax:
// ===========Client Side (Client Script) ================== var ga = new GlideAjax('MeuScriptInclude'); ga.addParam('sysparm_name', 'NomeDoMetodo'); ga.addParam('sysparm_nomeDoParametro', valorDoParametro); ga.getXMLAnswer(meuOutroCallback); function meuOutroCallback(answer, sysid) { alert(answer); } // =========== Server Side (Script Include) ================= NomeDoMetodo: function() { var meuParametro = this.getParameter("sysparm_nomeDoParametro"); return (meuParametro == "Brasil") ? ' É TETRA!' : 'Fomos surpreendidos...' ; }
Espero que tenham gostado e até a proxima!
Muito bom o artigo Hélio!
Explicou de maneira sucinta e prática, porém detalhou o suficiente para sair da superfície.
Obrigado Gustavo!
Quem nunca apanhou desse negócio não é mesmo? rs
Espero ter ajudado e toda crítica/sugestão é sempre bem-vinda!
Abraço!