Usar la biblioteca cliente de JavaScript (v2.0)

Advertencia: Esta página trata sobre las API anteriores de Google, las API de datos de Google, y solo es relevante para las API que aparecen en el directorio de las API de datos de Google, muchas de las cuales se reemplazaron con API más nuevas. Para obtener información sobre una API nueva específica, consulta la documentación de la API nueva. Para obtener información sobre cómo autorizar solicitudes con una API más reciente, consulta Autenticación y autorización de cuentas de Google.

En este documento, se describe cómo usar la biblioteca cliente de JavaScript para enviar consultas de la API de datos de Google y, luego, interpretar las respuestas mostradas.

Google proporciona un conjunto de bibliotecas cliente, en una variedad de lenguajes de programación, para interactuar con los servicios que tienen API de datos. Con estas bibliotecas, puedes crear solicitudes a la API, enviarlas a un servicio y recibir respuestas.

En este documento, se proporciona información general sobre el uso de la biblioteca cliente de JavaScript, junto con una serie de ejemplos de usos comunes.

Público

Este documento está orientado a los programadores de JavaScript que desean escribir aplicaciones cliente que pueden interactuar con servicios de datos de Google.

En este documento, se asume que comprendes las ideas generales detrás del protocolo de las API de datos de Google. También se supone que sabes programar en JavaScript.

Para obtener información de referencia sobre las clases y los métodos proporcionados por la biblioteca cliente, consulta la referencia de la API de la biblioteca cliente de JavaScript (en formato JSdoc).

Este documento está diseñado para leerse en orden. Cada ejemplo se basa en ejemplos anteriores.

Condiciones de Uso

Al usar la biblioteca cliente de JavaScript, aceptas cumplir las Condiciones de uso de la biblioteca cliente de Google JavaScript.

Descripción general del flujo de control y modelo de datos

La biblioteca cliente de JavaScript utiliza un conjunto de clases para representar los elementos que utilizan las API de datos de Google.

Nota: La representación subyacente de los datos es JSON, pero la biblioteca cliente proporciona una capa de abstracción para que no tengas que trabajar con los datos JSON directamente. Si deseas trabajar directamente con JSON, sin la biblioteca cliente, consulta Usa JSON con las API de datos de Google.

La biblioteca proporciona métodos que te permiten enviar y recibir datos de forma asíncrona desde un servicio que tiene una API de datos. Por ejemplo, el método google.gdata.calendar.CalendarService.getEventsFeed() envía una solicitud de feed para el Calendario de Google. Uno de los parámetros que pasas es una función de continuación, también conocida como callback; el servicio devuelve el feed, en formato JSON, llamando a la función de continuación. Luego, el cliente puede llamar a varios métodos get para usar los datos en forma de objetos JavaScript.

Para agregar una entrada nueva, crea la entrada con las clases y los métodos de la biblioteca cliente y, luego, llama al método feed.insertEntry() a fin de enviar la entrada nueva al servicio. Nuevamente, debes proporcionar una función de continuación, a la que llama el servicio cuando la entrada se agregó correctamente.

Si eres nuevo en JavaScript, el flujo de control puede resultar un poco confuso. En la mayoría de los casos, después de llamar a un método como getEventsFeed() o insertEntry(), finaliza la secuencia de comandos. La ejecución se reanuda en la función de continuación cuando el servicio muestra los datos solicitados. Por lo tanto, todo lo que su cliente haga con los datos que se muestren se debe hacer en la función de continuación, o se debe llamar desde esa función. Es posible que tengas que globalizar algunas variables para poder usarlas en varias funciones.

Para obtener más información sobre este estilo de programación, consulta "Estilo de paso de Continuation" en Wikipedia.

Acerca de los entornos compatibles

Actualmente, solo admitimos aplicaciones cliente de JavaScript que se ejecutan en una página web en un navegador. Los navegadores admitidos actualmente son:

  • Firefox 2.x y 3.x
  • Internet Explorer 6, 7 y 8
  • Safari 3.x y 4.x
  • Google Chrome (todas las versiones)

La biblioteca cliente de JavaScript controla toda la comunicación con el servidor del servicio. Si eres un desarrollador de JS con experiencia, es posible que estés pensando "¿Pero qué sucede con la misma política de origen?" La biblioteca cliente de JavaScript permite a tu cliente enviar solicitudes de datos de Google desde cualquier dominio y, a la vez, cumplir con el modelo de seguridad del navegador.

Para obtener una descripción general sobre la autenticación con las API de datos de Google, consulta la Descripción general de la autenticación de las API de datos de Google. En el resto de este documento, se asume que estás familiarizado con los conceptos básicos del funcionamiento de este sistema.

Aplicaciones cliente de muestra

Para ver la biblioteca cliente de JavaScript en acción, visita nuestra página de muestras.

Instructivo y ejemplos

En los siguientes ejemplos, se muestra cómo enviar varias solicitudes a la API de datos con la biblioteca cliente de JavaScript.

Para hacerlos más concretos, estos ejemplos muestran cómo interactuar con un servicio específico: Calendario de Google. Te indicaremos los lugares en que Calendario difiere de otros servicios de Google para ayudarte a adaptar estos ejemplos para usarlos con otros servicios. Para obtener más información sobre el Calendario, consulte el documento API de datos del Calendario de Google.

Cómo cargar la biblioteca

Antes de que tu cliente pueda usar la biblioteca cliente, debe solicitar al servidor el código de biblioteca cliente.

Comienza por usar una etiqueta <script> en la sección <head> de tu documento HTML para recuperar el cargador de la API de AJAX de Google:

<script type="text/javascript" src="https://www.google.com/jsapi"></script>

Puedes minimizar los recorridos de ida y vuelta a los servidores de Google y disminuir la latencia mediante la precarga de la biblioteca. Para precargar determinados paquetes directamente desde el cargador de la API de Google AJAX (sin usar google.load(), consulta los siguientes vínculos):

<script type="text/javascript"
      src="https://www.google.com/jsapi?autoload=%7Bmodules%3A%5B%7Bname%3Agdata%2Cversion%3A2.x%2Cpackages%3A%5Bblogger%2Ccontacts%5D%7D%5D%7D"></script>

Nota: La URL src de la secuencia de comandos debe estar completamente codificada como URL. Por ejemplo, el anterior es
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={modules:[{name:gdata,version:2.x,packages:[blogger,contacts]}]}"></script>.

Si no cargas módulos de forma automática, puedes cargar la biblioteca cliente de datos de Google con el siguiente ejemplo de tu código de configuración de JavaScript, después de recuperar el cargador común. Esta llamada se debe realizar desde la sección <head> de tu documento HTML (o desde un archivo JavaScript incluido con una etiqueta <script> en la sección <head> de tu documento HTML):

google.load("gdata", "2");

Como alternativa, puedes solicitar servicios específicos en lugar de toda la biblioteca. En este ejemplo, solo se descargan los paquetes de Blogger y Contactos:

google.load("gdata", "2.x", {packages: ["blogger", "contacts"]});

El segundo parámetro de google.load() es el número de versión solicitado de la biblioteca cliente de JavaScript.Nuestro esquema de numeración de versiones se basa en el que usa la API de Google Maps. Estos son los números de versión posibles y su significado:

"1"
De la segunda a la última revisión de la versión principal 1
"1.x"
La revisión más reciente de la versión principal 1.
"1.s"
La última versión estable de la versión principal 1. En ocasiones, declararemos que una versión determinada de la biblioteca cliente es "estable", según los comentarios que recibimos de los desarrolladores. Sin embargo, es posible que esa versión no tenga las funciones más recientes.
"1.0", "1.1", etcétera
Es una versión específica de la biblioteca, con un número de revisión principal y menor especificado.

Después de llamar a google.load(), debes indicarle al cargador que espere hasta que la página termine de cargarse y, luego, llama a tu código:

google.setOnLoadCallback(getMyFeed);

Donde getMyFeed() es una función definida en la siguiente sección de este documento. Usa este enfoque en lugar de tener un controlador onload adjunto al elemento <body>.

Cómo solicitar un feed sin autenticar

Para solicitar un feed no autenticado, agrega el siguiente código a tu archivo JavaScript o a una etiqueta <script> en tu archivo HTML.

En el siguiente código, primero se llama a getMyFeed() (mediante el cargador de la API de AJAX, como se describe en la sección anterior).

Llama a setupMyService() para crear una conexión (representada por un objeto CalendarService) con Calendario de Google. Quitamos el código de creación de servicio en una función independiente para la modularidad. Más adelante, modificaremos la función setupMyService(), según tus opciones de autenticación.

Después de configurar el servicio, getMyFeed() llama al método getEventsFeed() de la biblioteca cliente para solicitar el feed.

Especificaremos la URL del feed en una variable global para que pueda usarse en funciones posteriores. En este ejemplo, usamos la URL del feed público (no autenticado) de un usuario llamado liz@gmail.com. También puedes usar default en lugar de la dirección de correo electrónico del usuario para representar al usuario autenticado.

var feedUrl = "http://www.google.com/calendar/feeds/liz@gmail.com/public/full";

function setupMyService() {
  var myService = new google.gdata.calendar.CalendarService('exampleCo-exampleApp-1');
  return myService;
}

function getMyFeed() {
  myService = setupMyService();

  myService.getEventsFeed(feedUrl, handleMyFeed, handleError);
}

Ten en cuenta que convertiremos myService en una variable global para facilitar su uso en funciones posteriores.

Para que el código anterior funcione en su propio cliente, debe usar la dirección de correo electrónico de un usuario real para una cuenta de Calendario con un calendario compartido de forma pública.

Nota: Cuando creas un nuevo objeto CalendarService, la biblioteca cliente llama a un método llamado google.gdata.client.init(), que verifica que el navegador en el que se ejecuta el cliente sea compatible. Si se produce un error, la biblioteca cliente mostrará un mensaje de error al usuario. Si deseas manejar este tipo de error por tu cuenta, puedes llamar a google.gdata.client.init(handleInitError) de forma explícita antes de crear el servicio, en el que handleInitError() es tu función. Si se produce un error init, tu función recibe un objeto de error estándar. Puedes hacer lo que quieras con ese objeto.

En la llamada a getEventsFeed(), el segundo argumento es handleMyFeed, que es una función de devolución de llamada. Consulta la información a continuación. El Calendario de Google procesa la solicitud y, si la solicitud se realizó correctamente, pasa un objeto "raíz del feed" con el feed solicitado a la devolución de llamada. Una raíz de feed es un objeto contenedor que contiene un feed.

El tercer argumento para getEventsFeed() es una función opcional de manejo de errores. Si se encuentra un error, la biblioteca cliente llama al controlador de error especificado en lugar de la función de devolución de llamada de éxito. El objeto que la biblioteca cliente pasa como argumento al controlador de error es una instancia del objeto Error de JavaScript, con una propiedad cause adicional.

A continuación, te indicamos algunas versiones simples de la función de devolución de llamada y el controlador de errores:

function handleMyFeed(myResultsFeedRoot) {
  alert("This feed's title is: " + myResultsFeedRoot.feed.getTitle().getText());
}

function handleError(e) {
  alert("There was an error!");
  alert(e.cause ? e.cause.statusText : e.message);
}

Abordamos los errores simplemente mostrándolos al usuario. Es probable que el controlador de errores de tu cliente sea más sofisticado. En algunos contextos, es posible que no se especifique una causa, por lo que, en esos casos, nuestro controlador de errores de ejemplo muestra la propiedad message estándar.

Tenga en cuenta que, debido a que este código no realiza la autenticación, solo puede usarlo para obtener un feed público.

Autenticando

La biblioteca cliente de JavaScript se puede usar en dos modos. Si estás escribiendo un gadget, utiliza una función llamada Proxy OAuth para autenticación. Si se accede a este desde una aplicación de JavaScript independiente, utiliza el sistema de autenticación de AuthSub. Para obtener más información sobre la autenticación, consulta el documento Descripción general de la autenticación de las API de datos de Google. En el resto de esta sección, se asume que estás familiarizado con los conceptos básicos del funcionamiento de este sistema.

Antes de usar la autenticación con el código de muestra que se proporciona en este documento, cambie la URL del feed de pública a privada:

var feedUrl = "http://www.google.com/calendar/feeds/liz@gmail.com/private/full";

Autentica en un cliente web con AuthSub

El sistema de autorización de Google "AuthSub for JavaScript" ya no está disponible.

En su lugar, recomendamos usar OAuth 2.0 para aplicaciones del cliente.

Autenticación en un gadget con el proxy OAuth

A continuación te presentamos un resumen de lo que sucede durante el proceso de autenticación de un gadget:

  1. Tu gadget se carga por primera vez e intenta acceder a los datos del usuario con una de las API de datos de Google.
  2. La solicitud falla porque el usuario aún no ha otorgado acceso a sus datos. El objeto de respuesta contiene una URL (en response.oauthApprovalUrl) para la página de aprobación de OAuth. Tu gadget debe proporcionar un método para abrir una nueva ventana con esa URL.
  3. En la página de aprobación, el usuario elige conceder o denegar el acceso a tu gadget. Si se ejecuta de forma correcta, se redirecciona al usuario a la página de oauth_callback que especifiques. Para obtener la mejor experiencia del usuario, usa http://oauth.gmodules.com/gadgets/oauthcallback.
  4. A continuación, el usuario cierra la ventana emergente. Para ayudar a notificar a tu gadget que el usuario ha dado la aprobación, hemos proporcionado un controlador emergente que puedes utilizar para detectar el cierre de la ventana de aprobación. De forma alternativa, tu gadget puede mostrar un vínculo (p.ej., "Aprobé el acceso") para que el usuario haga clic manualmente después de que se cierre esta ventana.
  5. Tu gadget intenta acceder a la API de datos de Google por segunda vez mediante una nueva solicitud de datos del usuario. Este intento se realizó correctamente.
  6. Tu gadget se autenticó y puede comenzar a funcionar normalmente.

En tu gadget, agrega un elemento <OAuth> en la sección <ModulePrefs>:

<ModulePrefs>
...
<OAuth>
  <Service name="google">
    <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> 
    <Request url="https://www.google.com/accounts/OAuthGetRequestToken?
                  scope=http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/" method="GET" /> 
    <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken?
                        oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> 
  </Service>
</OAuth>
...
</ModulePrefs>

En esta sección, cambia los siguientes parámetros de búsqueda:

  • scope

    Un parámetro obligatorio en la URL de la solicitud. Tu gadget sólo podrá acceder a los datos de los scope que se utilicen en este parámetro. En este ejemplo, el gadget accederá a tus datos de Blogger y Calendar. Un gadget puede solicitar datos para un solo ámbito o para varios ámbitos (como en este ejemplo).

  • oauth_callback

    Un parámetro opcional en la URL de autorización. La página de aprobación de OAuth redireccionará a esta URL después de que el usuario apruebe el acceso a sus datos. Puede optar por omitir este parámetro, establecer su propia "página aprobada" o, si lo desea, utilizar una http://oauth.gmodules.com/gadgets/oauthcallback. La última proporciona la mejor experiencia a los usuarios cuando instalan tu gadget por primera vez. Esa página proporciona un fragmento de código JavaScript que cierra automáticamente la ventana emergente.

A continuación, carga la biblioteca cliente de JavaScript en la sección <Content> de tu gadget. Modifica la función setupMyService() de los ejemplos anteriores para llamar al método useOAuth() del objeto de servicio. Esto indica al gadget que utilice el proxy de OAuth para realizar la autenticación en lugar de AuthSub. Con la siguiente plantilla, deberías comenzar:

<Content type="html">
<![CDATA[
  ...
  <script src="https://www.google.com/jsapi"></script>
  <script type="text/javascript">
    var myService = null;
    
    function setupMyService() {
      myService = new google.gdata.calendar.CalendarService('exampleCo-exampleApp-1');
      myService.useOAuth('google');
      fetchData();
    }
    
    function initGadget() {
      google.load('gdata', '2.x');
      google.setOnLoadCallback(setupMyService);
    }

    function fetchData() {            
      var callback = function(response) {
        if (response.oauthApprovalUrl) {
        
          // TODO: Display "Sign in" link (response.oauthApprovalUrl contains the URL) 
          
        } else if (response.feed) {
        
          // TODO: show results
          
        } else {
        
          // TODO: handle the error
          
        }
      };

      myService.getEventsFeed('http://www.google.com/calendar/feeds/default/public/full', callback, callback);
    }
    
    gadgets.util.registerOnLoadHandler(initGadget);
  </script>
  ...
]]> 
</Content>

Ten en cuenta que se quitó la llamada a google.accounts.user.login(scope). El proxy se encarga de la autenticación por ti.

Para obtener más información sobre cómo escribir gadgets de la API de datos de Google, incluidos los detalles de lo que fetchData() debe contener, consulta nuestro artículo sobre Cómo crear un gadget de datos de Google o consulta la documentación completa de escritura de gadgets de OAuth.

Cómo insertar un nuevo elemento

Para crear un nuevo evento de calendario, continúa la ejecución del ejemplo anterior modificando el final de la función handleMyFeed() a fin de llamar a una nueva:

function handleMyFeed(myResultsFeedRoot) {
  alert("This feed's title is: " + myResultsFeedRoot.feed.getTitle().getText());
  insertIntoMyFeed(myResultsFeedRoot);
}

En la función nueva, primero usa el constructor CalendarEventEntry para crear la entrada nueva. Luego, inserta la entrada y proporciona una devolución de llamada para que el servicio la llame cuando finalice la inserción.

function insertIntoMyFeed(feedRoot) {
  var newEntry = new google.gdata.calendar.CalendarEventEntry({
      authors: [{
        name: "Elizabeth Bennet",
        email: "liz@gmail.com"
      }],
      title: {
        type: 'text', 
        text: 'Tennis with Darcy'
      },
      content: {
        type: 'text', 
        text: 'Meet for a quick lesson'
      },
      locations: [{
        rel: "g.event",
        label: "Event location",
        valueString: "Netherfield Park tennis court"
      }],
      times: [{
        startTime: google.gdata.DateTime.fromIso8601("2007-09-23T18:00:00.000Z"),
        endTime: google.gdata.DateTime.fromIso8601("2007-09-23T19:00:00.000Z")
      }]
  });
  feedRoot.feed.insertEntry(newEntry, handleMyInsertedEntry, handleError);
}

Ten en cuenta que el nombre de cada propiedad de objeto utilizada en el constructor coincide con el nombre del método establecedor usado para esa propiedad. (En lugar de, por ejemplo, hacer coincidir el nombre del campo JSON correspondiente).

Además, ten en cuenta que no puedes proporcionar solo strings de fecha y hora ISO 8601 para startTime y endTime; primero debes ejecutar esas strings a través del método fromIso8601().

El servicio muestra una copia de la entrada insertada como un objeto entryRoot y pasa ese objeto a la devolución de llamada:

function handleMyInsertedEntry(insertedEntryRoot) {
  alert("Entry inserted. The title is: " + insertedEntryRoot.entry.getTitle().getText());
  alert("The timestamp is: " + insertedEntryRoot.entry.getTimes()[0].startTime);
}

Cómo solicitar una entrada específica

A fin de solicitar una entrada específica, primero modifica la función handleMyInsertedEntry() para llamar a una nueva función de solicitud de entrada:

function handleMyInsertedEntry(insertedEntryRoot) {
  alert("Entry inserted. The title is: " + insertedEntryRoot.entry.getTitle().getText());
  alert("The timestamp is: " + insertedEntryRoot.entry.getTimes()[0].startTime);
  requestMySpecificEntry(insertedEntryRoot.entry.getSelfLink().getHref());
}

El siguiente código te permite solicitar la entrada específica que insertaste en el ejemplo anterior.

En el contexto de esta serie de ejemplos, la recuperación de esa entrada no es realmente necesaria, ya que Calendario ya mostró la entrada insertada, pero es posible aplicar la misma técnica siempre que conozcas el URI de una entrada.

function requestMySpecificEntry(entryURI) {
  myService.getEventsEntry(entryURI, handleMySpecificEntry, handleError);
}

function handleMySpecificEntry(retrievedEntryRoot) {
  myEntryRoot = retrievedEntryRoot; // Global variable for later use
  alert("This entry's title is: " + retrievedEntryRoot.entry.getTitle().getText());
}

En esencia, este ejemplo es el mismo que el ejemplo de getEventsFeed(), excepto que estamos llamando al método getEventEntry() del servicio para obtener una entrada específica y el URI es un poco diferente: usa "default" para referirse al calendario principal del usuario autenticado y tiene un ID de entrada al final.

Además, debemos poder usar la entrada recuperada más tarde, así que la copiamos en una variable global.

Busca entradas

Para realizar una búsqueda en el texto completo, primero modifica la función handleMySpecificEntry() a fin de llamar a una nueva función de búsqueda:

function handleMySpecificEntry(retrievedEntryRoot) {
  myEntryRoot = retrievedEntryRoot; // Global variable for later use
  alert("This entry's title is: " + retrievedEntryRoot.entry.getTitle().getText());
  searchMyFeed();
}

Luego, para recuperar la primera coincidencia de la búsqueda, usa el siguiente código:

function searchMyFeed() {
  var myQuery = new google.gdata.calendar.CalendarEventQuery(feedUrl);
  myQuery.setFullTextQuery("Tennis");
  myQuery.setMaxResults(10);
  myService.getEventsFeed(myQuery, handleMyQueryResults, handleError);
}

function handleMyQueryResults(myResultsFeedRoot) {
  if (myResultsFeedRoot.feed.getEntries()[0]) {
    alert("The first search-match entry's title is: " + myResultsFeedRoot.feed.getEntries()[0].getTitle().getText());
  }
  else {
    alert("There are no entries that match the search query.");
  }
}

Actualizar un elemento

Si quieres actualizar un elemento existente, primero agrega una línea al final de handleMyQueryResults() para llamar a una nueva función de actualización:

  updateMyEntry();

Luego, usa el siguiente código. En este ejemplo, cambiamos el título de la entrada recuperada previamente (que se encontraba en el objeto global llamado myEntryRoot en un ejemplo anterior) de su texto antiguo ("Tenis con Darcy") a "Reunión importante".

function updateMyEntry() {
  myEntryRoot.entry.getTitle().setText("Important meeting");
  myEntryRoot.entry.updateEntry(handleMyUpdatedEntry, handleError);
}

function handleMyUpdatedEntry(updatedEntryRoot) {
  alert("Entry updated. The new title is: " + updatedEntryRoot.entry.getTitle().getText());
}

Al igual que con todos los métodos de Calendario, el método updateEntry() determina automáticamente el URI de edición correcto que se debe usar para actualizar la entrada, por lo que no tienes que proporcionar ese URI de forma explícita.

Eliminar un elemento

Para borrar la entrada actualizada, primero agrega una línea a handleMyUpdatedEntry():

 deleteMyEntry(updatedEntryRoot);

Luego, usa el siguiente código:

function deleteMyEntry(updatedEntryRoot) {
  updatedEntryRoot.entry.deleteEntry(handleMyDeletedEntry, handleError);
}

function handleMyDeletedEntry() {
  alert("Entry deleted");
}

Una vez más, el método deleteEntry() determina automáticamente el URI de edición correcto que se usará para borrar la entrada.

Ten en cuenta que no se muestra ninguna entrada. Si se llama a la devolución de llamada, significa que se borró correctamente. Si la eliminación falla, deleteEntry() llama a handleError() en lugar de llamar a handleMyDeletedEntry().

Usa ETags

Nota: Las ETag solo se pueden usar con servicios que ejecutan el Protocolo de datos de Google versión 2.0.

Introducción

La versión 2 del cliente de Google Data JavaScript presenta compatibilidad con ETags. Los ETag son identificadores que especifican una versión particular de una entrada en particular; esto es importante en dos casos:

  • Hacer una “recuperación condicional” en la que un cliente solicita una entrada y el servidor la envía solo si esta cambió desde la última vez que el cliente la solicitó.
  • Garantizar que varios clientes no reemplacen los cambios de los demás sin darse cuenta Para esto, las API de datos realizan actualizaciones y eliminaciones si el cliente especifica una ETag antigua para la entrada.

Existen dos tipos de ETag: débiles y fuertes. Una ETag débil siempre comienza con W/, por ejemplo: W/"D08FQn8-eil7ImA9WxZbFEw". No se garantiza que los ETag débiles cambien cuando la entrada cambia, de modo que HTTP permite que se los use solo para la recuperación condicional. Los ETag fuertes identifican una versión específica de una entrada específica y se pueden usar para la recuperación condicional y durante las actualizaciones o eliminaciones para evitar sobrescribir los cambios de otros clientes. Debido a esta distinción, la biblioteca cliente no te permitirá enviar ETags débiles con una solicitud de actualización o eliminación.

Las ETag se pueden encontrar en dos ubicaciones en la respuesta del servidor:

  • En el encabezado HTTP ETag.
  • En el feed o la entrada, como el atributo gd:etag.

Si un servicio es compatible con la versión 2, cada feed y objeto de entrada tendrán un método getEtag() para recuperar el valor de la ETag.

El cliente de JavaScript admite dos métodos para incluir ETags con una solicitud. El primero es el nuevo objeto opt_params. Todas las funciones get, update y insert de la versión 2 de la biblioteca cliente tienen un nuevo parámetro opt_params. Este objeto se usa para especificar parámetros opcionales cuando se realiza una solicitud. Por ahora, 'etag' es el único parámetro opcional admitido (aunque se pueden ingresar otros parámetros en el futuro). Por ejemplo, puedes agregar una ETag a una solicitud GET como la siguiente:

var opt_params = {};
opt_params['etag'] = 'ETAG GOES HERE';
service.getFeed(uri, successHandler, errorHandler, opt_params);

También puedes agregar una ETag directamente a un feed o un objeto de entrada llamando al método setEtag() en el feed o la entrada.

Puedes obtener más información sobre las ETags en la Referencia del protocolo de datos de Google.

Uso de ETags para recuperar datos

Las ETag pueden ayudar a reducir el ancho de banda y el tiempo de ejecución al recuperar datos. Se puede incluir una ETag en una solicitud GET con el If-None-Match header:

If-None-Match: ETAG GOES HERE

Si la ETag coincide con la versión actual del feed o la entrada, el servidor responde con una respuesta 304 NOT MODIFIED y un cuerpo vacío. De lo contrario, el servidor responde con una respuesta 200 OK y los datos del feed o de la entrada.

Puedes usar ETags en el cliente de JavaScript al incluir un parámetro 'etag' cuando realizas la solicitud:

var etag = feed.getEtag(); // Feed loaded from a previous request
var opt_params = {};
opt_params['etag'] = etag;
service.getFeed(feedUrl, successHandler, errorHandler, opt_params);

Las recuperaciones condicionales funcionan con ETags fuertes y débiles. Si el ETag es una coincidencia, se llamará al controlador de error con una respuesta 304:

function successHandler(feedRoot) {
  // 200 response
  // Update UI to display updates
}

function errorHandler(errorObj) {
  if (errorObj.cause.getStatus() == 304) {
    // 304 response, do nothing
  }
  // otherwise the response is some other error
}

Observa el ejemplo Recuperación condicional mediante Blogger para ver un ejemplo más práctico de uso de ETags en el cliente de JavaScript. Este ejemplo sondea Blogger en intervalos de 5 segundos y busca actualizaciones para tu blog. Cuando hay cambios, la muestra actualiza una lista de publicaciones.

Uso de ETags para actualizar y eliminar datos

El uso de ETags en las solicitudes update/delete garantiza que múltiples clientes no sobrescriban accidentalmente los cambios del otro. En este caso, se incluye una ETag con el encabezado If-Match:

If-Match: ETAG GOES HERE

Si el ETag en la solicitud coincide con el ETag en el servidor, la actualización/eliminación será exitosa. Sin embargo, una discrepancia de ETag indica que la entrada cambió y que la actualización/eliminación falla. En este caso, la aplicación debe solicitar una instancia nueva de los datos y, luego, intentar actualizar o borrar de nuevo.

En ciertos casos, es posible que desees forzar tus cambios, sin importar cualquier otro cambio en la entrada. Para ello, pasa un elemento * al encabezado If-Match:

If-Match: *

Tenga en cuenta que esto anulará los cambios que realicen otros clientes, así que utilícelo detenidamente.

Solo puedes actualizar o borrar una entrada con una ETag segura. Especificar un ETag débil dará como resultado un error. Para protegerse de este caso, el cliente de JavaScript no establecerá ETags débiles en las solicitudes de actualización y eliminación.

Los ETag se usan de la misma manera que las recuperaciones condicionales:

function updateData(entry, service) {
  var etag = entry.getEtag();
  var opt_params = {};
  opt_params['etag'] = etag; // Or use '*' to force an update.
  service.updateEntry(successHandler, errorHandler, opt_params);
}

function successHandler(response) {
  // Successful update
}

function errorHandler(errorObj) {
  // ERROR - Update failed. Could be due to an ETag mismatch, but check the
  // error message to make sure. An ETag error will be in the format:
  // Mismatch: etags = ["Qnc-fTVSLyp7ImA9WxJbFEsDRAw."], version = [1249675665358000]
}

Al realizar actualizaciones, una ETag se puede especificar en dos lugares:

  1. En la entrada misma, con los métodos getEtag() y setEtag()
  2. En el encabezado, usa el objeto opt_params (como se mostró antes).

Una entrada cargada desde una solicitud GET anterior ya tendrá un campo ETag configurado. Por lo tanto, especificar la misma ETag en el objeto opt_params es redundante. En los casos en que se especifique una ETag en el cuerpo de la entrada y en la opt_params, tendrá prioridad la ETag en la opt_params. Esto puede resultar un poco confuso, así que, si tienes problemas con las actualizaciones condicionales, asegúrate de verificar la ETag en la entrada y en el objeto opt_params.

Para facilitar las cosas, las clases google.gdata.Entry también tienen sus propios métodos updateEntry() y deleteEntry(). Si la clase de entrada ya tiene una ETag, no tienes que agregarla a la solicitud; la biblioteca cliente lo hará automáticamente. Por ejemplo:

// entry was loaded from a previous request.  No need to specify
// an ETag in opt_params here, it is added automatically.
entry.deleteEntry(successHandler, errorHandler);

Esto te da el beneficio de tener ETags sin preocuparte si los configuras correctamente. Sin embargo, si deseas forzar la actualización mediante '*', siempre debes incluir el objeto opt_params con 'etag' = '*'.

Puedes ver las actualizaciones condicionales en funcionamiento en Actualizaciones condicionales en Contactos. La muestra primero crea un grupo de contactos de prueba en el que se crearán todos los datos que se usan en esta muestra. Puedes borrar este grupo de contactos cuando termines de usar la muestra. Luego, la muestra carga dos iframes con el contenido del grupo de contactos. Puedes hacer actualizaciones en un iframe y ver cómo afectan las actualizaciones en el otro. Visita la muestra para obtener más detalles sobre cómo usarla.

Ejemplos

Reference

Para obtener información de referencia sobre las clases y los métodos proporcionados por la biblioteca cliente, consulta la referencia de la API de la biblioteca cliente de JavaScript (en formato JSdoc).

Volver al principio