Usando Promises con JQuery y API REST de SharePoint


Hola de nuevo a todos,

Empezando a trabajar con Javascript de forma intensiva, me he topado con la necesidad de usar un concepto del que había oído hablar hace tiempo, pero que hasta ahora no me había hecho falta. Este concepto es lo que se conoce como Promesas o Promises.

Cuando estamos trabajando con varias APIs a través de peticiones asíncronas o con una API pero realizamos varias peticiones a la vez, al final te puedes encontrar con el problema de que, peticiones que necesitas que se ejecuten después que otras lo están haciendo antes, por la propia naturaleza de las llamadas asíncronas. Puede ocurrir también que, funciones que necesitas que se ejecuten al finalizar las llamadas asíncronas lo estén haciendo antes. Para evitar esto puedes pensar en un primer momento en una montón de llamadas asíncronas anidadas en el callback de éxito de las llamadas asíncronas o por el contrario, usar las promesas.

¿Que son las promesas?

Para explicar lo que son las promesas, voy a tomar prestado la explicación de la siguiente entrada de un blog que he encontrado:

http://www.funcion13.com/2012/03/26/comprendiendo-promesas-y-deferreds-en-jquery/

La promesa (promise) en sí, es un objeto que representa un evento en el tiempo, como la llegada de datos de una petición asíncrona o el fin del procesamiento de todos los datos obtenidos en una función asíncrona. Un objeto promise es una versión de solo lectura de un objeto deferred.

Los deferred comienzan en estado pendiente, y es lógico si lo pensáis, pudiendo pasar a estado resuelto (la tarea se completó) o rechazado (si es que falló). En el momento en que un deferred cambie su estado a resuelto o rechazado no podrá cambiar nunca más.

Vamos a usar las promesas para manejar peticiones asíncronas, y controlar que se reciba una respuesta sea correcta o no. Además, con JQuery, podremos controlar, la respuesta de varias peticiones asíncronas por medio de promesas que se ejecutan simultáneamente. El código javascript, además, quedará mucho más ordenado.

Os dejo algunos enlaces que he usado yo para entender bien el concepto de promises.

http://www.danieldemmel.me/blog/2013/03/22/an-introduction-to-jquery-deferred-slash-promise/

http://joseoncode.com/2011/09/26/a-walkthrough-jquery-deferred-and-promise/

http://api.jquery.com/deferred.promise/

¿Cómo se usan las promesas?

En el ejemplo que os voy a mostrar a continuación, he usado las promesas para trabajar con la API REST de SharePoint. En mi caso, en una aplicación que estoy desarrollando, necesitaba hacer varias peticiones API REST para saber si varias listas existían para, en función de si lo hacían o no indicarlo al usuario para darle la oportunidad de crearlas.

El problema me surgía por la dificultad de controlar el resultado de las peticiones, ya que al ser asíncronas, las evaluaciones de su resultado se hacían antes de que la petición se hubiera realizado realmente, por lo que no funcionaba como quería que lo hiciera.

Para ello he usado el concepto de promesas, por medio de ellas, puedo controlar que todas las peticiones se hagan y den un resultado, y esperar hasta que se obtenga la respuesta de todas para llevar la acción que corresponda. Voy a mostraros el código y posteriormente explicarlo, en mi caso he usado la librería JQuery y el objeto Deferred de la misma:

function ExistList(listname) {

        var deferred = $.Deferred();

        var appweburl = GetQueryStringParameter("SPAppWebUrl");
        var hostweburl = GetQueryStringParameter("SPHostUrl");

        var executor = new SP.RequestExecutor(appweburl);

        executor.executeAsync({
            method: "GET",
            url: appweburl + "/_api/SP.AppContextSite(@target)/web/Lists/GetByTitle('" + listname + "')?@target='" + hostweburl + "'",
            headers: { "Accept": "application/json; odata=verbose" },
            success: function (data) {
                deferred.resolve();
            },
            error: function (data) {
                console.log(data);
                deferred.reject();
            }
        });

        return deferred.promise();
    }

function Validation(){

            var list1 = "List1";
            var list2 = "List2";

            $.when(ExistList(list1), ExistList(list2))
             .done(function () {

             })
             .fail(function () {
                 RedirectApp("Install.aspx");
             });
                
        }
  • El primer aspecto importante se encuentra en la función ExistList y es el objeto deferred, se crea al inicio de la función y al final de la función se devuelve la promesa. Dentro de la función se hace la petición asíncrona y en el callback de éxito y de error de la misma llamada, se indica si la promesa se ha cumplido (por medio de deferred.resolve()) o no (por medio de deferred.reject()) respectivamente.
  • En la función de validación el primer elemento importante es la llamada $.when() a la que le indicaremos como parámetro (tal y como podemos ver), todas las promesas que queremos que espere a obtener resultado. Los callback no se ejecutarán hasta que no se haya recibido la respuesta de todas las promesas indicadas como parámetro de la llamada.
  • En el caso de que todas las promesas hayan respondido positivamente se utiliza el callback de la llamada done.
  • En el caso de que alguna de las promesas haya respondido negativamente se ejecuta el callbak de la llamada fail

En ocasiones también podremos encontrarnos que se usa la llamada then que lleva como parámetros los dos callback de éxito y error, pero a mi me ha resultado más claro usar la llamada done y fail.

Cuando trabajamos con JQuery y usamos la llamada $.ajax(), ya de por sí devuelve una promesa por lo que no debemos encapsularla en una función para crear el objeto deferred.

Y con esto espero que si alguien no sabía o no había trabajado habitualmente con promesas, encuentre aquí como trabajar con ellas. Aunque el trabajo con promesas no es una novedad, hasta ahora no había necesitado trabajar con ellas, me ha resultado muy fácil, además de que el código queda muchísimo más limpio y organizado.

Un saludo a todos.

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s