Descripción general de las secuencias de comandos

Con App Maker, puedes crear apps relativamente complejas sin codificación. Sin embargo, a veces, necesitas una funcionalidad que los widgets y el editor de modelos no pueden proporcionar por sí solos. El editor de secuencias de comandos de JavaScript de App Maker puede ayudarte con eso.

Existen dos tipos de secuencias de comandos en App Maker: las secuencias de comandos del cliente que se ejecutan en los navegadores de los usuarios y las secuencias de comandos del servidor que se ejecutan en los servidores de App Maker. A continuación, se muestran algunos ejemplos de lo que puedes hacer con las secuencias de comandos en App Maker:

  • Realizar cálculos y operaciones lógicas específicos de la app
  • Conectarte a servicios web externos
  • Crear verificaciones de permisos personalizadas
  • Y realizar muchas acciones más…

Secuencias de comandos del cliente y del servidor

Aunque las secuencias de comandos del cliente y del servidor ejecutan JavaScript, se diferencian por el lugar donde se usan y en cómo funcionan.

Datos básicos de la secuencia de comandos del cliente

  • Las secuencias de comandos del cliente se ejecutan en los navegadores de los usuarios. Pueden acceder al DOM, al almacenamiento local del navegador y más.
  • Las secuencias de comandos del cliente pueden editar las propiedades de widgets. App Maker expone los widgets como objetos de JavaScript, por lo que puedes cambiar su apariencia, eventos y otras propiedades de manera programática.
  • Las secuencias de comandos del cliente bloquean el navegador. Para que las apps se mantengan responsivas, se deben evitar los cálculos complejos en las secuencias de comandos del cliente.

  • Las API de cliente son asíncronas. Algunas llamadas a la secuencia de comandos del cliente se ejecutan fuera de orden. Consulta el ejemplo trabaja con modelos de datos que se muestra a continuación para obtener más detalles.

  • Las secuencias de comandos del cliente no son seguras. Los usuarios avanzados pueden ver y cambiar las secuencias de comandos del cliente con las herramientas del navegador. No dependas de ellos cuando se trata de la seguridad o coherencia de los datos.

Datos básicos de la secuencia de comandos del servidor

  • Las secuencias de comandos del servidor se ejecutan en Apps Script. Pueden acceder a las bases de datos directamente y usar las API de Apps Script como calendario, correo electrónico y más.
  • Las secuencias de comandos del servidor no mantienen el estado entre las solicitudes. Se ejecutan en servidores distribuidos, por lo que cada vez que llames a una secuencia de comandos, sus variables globales estarán vacías.
  • Las secuencias de comandos del servidor a veces están sujetas a cuotas. Las llamadas a los servicios de Apps Script están limitadas por cuotas diarias.
  • Las secuencias de comandos del servidor pueden ser seguras. A diferencia de las secuencias de comandos del cliente, puedes confiar en las secuencias de comandos del servidor para controlar el acceso a datos sensibles. Úsalas para auditar y hacer cumplir la coherencia de los datos.

Ejemplos de secuencias de comandos

La forma más fácil de entender la diferencia entre las secuencias de comandos del cliente y del servidor es mediante un ejemplo. Las secuencia de comandos que se muestran a continuación son parte de una app de lista de tareas pendientes que permite a los usuarios crear múltiples listas de tareas, cada una con varios elementos que representan tareas pendientes.

Cliente: interactúa con páginas y widgets

La secuencia de comandos onClick para DeleteTodoListButton cambia a una página de confirmación cuando un usuario hace clic en el siguiente botón:

app.showPage(app.pages.DeleteTodoListConfirmationView);

Cliente: implementa vinculaciones de propiedad

La secuencia de comandos es una expresión de vinculación para la propiedad enabled de DeleteTodoListButton. Garantiza que el botón solo esté habilitado cuando no haya elementos de tareas pendientes en una lista, para que los usuarios solo puedan borrar listas de tareas vacías.

@datasource.item != null && @datasource.item.TodoItems.length == 0

Cliente y servidor: trabaja con modelos de datos

Cliente:

La secuencia de comandos crea y selecciona una nueva lista de tareas pendientes. Primero, llama a una secuencia de comandos del servidor para crear un nuevo registro de lista, luego, vuelve a cargar el modelo TodoList y, al final, selecciona la lista recién creada.

function onCreateTodoListClick() {
  var datasource = app.datasources.TodoList;
  google.script.run.withSuccessHandler(function(newKey) {

    // When created, redisplay todo lists.
    datasource.load(function() {

      // When reloaded, select new todo list.
      datasource.selectKey(newKey);
    });
  }).createTodoListWithItem();
}

Puede que notes que el código no coincide con el orden de operaciones anterior. Esto se debe a que la secuencia de comandos, como muchas secuencias de comandos del cliente, se ejecuta de forma asíncrona. La secuencia de comandos no puede ejecutar createTodoListWithItem() y luego load(), ya que, por ser asíncronas, no se puede garantizar que se creará una nueva lista de tareas antes de que se vuelva a cargar la fuente de datos.

En su lugar, createTodoListWithItem() llama a load() con una devolución de llamada que solo se ejecuta después de que se crea un elemento de la lista de tareas pendientes de forma correcta. Obtén más información sobre secuencias de comandos asíncronas y devoluciones de llamada en Secuencias de comandos del cliente.

Servidor:

La secuencia de comandos del servidor es createTodoListWithItem(), llamada desde la secuencia de comandos del cliente que se mostró con anterioridad. Accede a la base de datos de la app a fin de crear una nueva lista de tareas y un elemento para esa lista, y luego muestra la Key de la lista.

function createTodoListWithItem() {
  // Automatically number todo lists for the user.
  var lock = LockService.getScriptLock();
  lock.waitLock(10000);
  var query = app.models.TodoList.newQuery();
  var allTodoLists = query.run();
  var todoList = app.models.TodoList.newRecord();
  var newListNumber = allTodoLists.length + 1;
  todoList.name = "My list " + newListNumber;
  app.saveRecords([todoList]);
  lock.releaseLock();

  // Create first todo item for user convenience.
  var todoItem = app.models.TodoItem.newRecord();
  todoItem.TodoList = todoList;
  app.saveRecords([todoItem]);
  return todoList._key;
}

Las secuencias de comandos del servidor no guardan los datos de forma automática, por lo que la secuencia de comandos llama a saveRecords() para guardar los cambios en el modelo. Recuerda hacer lo mismo cuando escribas tus propias secuencias de comandos que crean o editan registros.

La secuencia de comandos también usa el bloqueo para garantizar la coherencia de los datos. Obtén más información sobre el bloqueo en Secuencia de comandos del servidor.

Servidor: seguridad, auditoría y coherencia de datos

Las secuencias de comandos del servidor te ayudan a mantener tus datos coherentes y seguros. La secuencia de comandos anterior usó el servicio de bloqueo para lograr la atomicidad de las operaciones de consulta y creación.

También puedes implementar permisos personalizados mediante excepciones para no permitir ciertos eventos del modelo. Por ejemplo, puedes agregar el siguiente fragmento al evento onDelete() de un modelo para evitar la eliminación de registros:

throw "Deletions now allowed";

También puedes crear auditorías con el controlador onCreate():

var email = Session.getActiveUser().getEmail();
record.setAudit("Created on " + new Date() + " by user " + email + "\n");

Cliente y servidor: obtén datos de otras URL

Cliente:

Usa XMLHttpRequest o el widget HtmlArea de App Maker para incorporar un IFRAME.

Servidor:

Usa el Servicio de recuperación de URL de Apps Script.

Cliente: integra bibliotecas personalizadas de JavaScript

Existen las siguientes formas de cargar bibliotecas externas de JavaScript, según la biblioteca:

JSHint para validación de secuencia de comandos

App Maker es compatible con algunas directivas de JSHint. Por ejemplo, puedes usar la directiva de ignore a fin de desactivar el verificador estático para un bloque de código:

/* jshint unused: true, eqnull: false */
var w = 3;   // Warning: w is defined but never used.
alert(10 == null); // Warning: use '===' to compare with 'null'.

/* jshint ignore:start */
var y = 4;     // No warning.
alert(10 == null); //  No warning.
/* jshint ignore:end */

var a = 5;   // Warning: a is defined but never used.
alert(10 == null); // Warning: use '===' to compare with 'null'.

Para obtener más información sobre JSHint, consulta la documentación de JSHint.