2012-08-02 9 views
6

Siguiendo los estándares REST típicos, dividí mis recursos en puntos finales y llamadas separados. Los dos objetos principales en cuestión aquí son List y Item (y, por supuesto, una lista tiene una lista de elementos, así como algunos otros datos asociados a ella).¿Cómo hacer un ciclo asincrónico limpio?

lo tanto, si un usuario quiere recuperar sus listas, se podría realizar una solicitud GET a api/Lists

continuación, el usuario podría querer conseguir los artículos en una de esas listas y hacer un GET a api/ListItems/4, donde se encontró 4 desde List.listId recuperado en la llamada anterior.

Esto está muy bien: el atributo options.complete de $.ajax me permite apuntar a un método de devolución de llamada, por lo que puedo simplificar estos dos eventos.

Pero las cosas se ponen muy complicadas si quiero obtener los elementos para todos las listas en cuestión. Por ejemplo, supongamos que tengo una función de biblioteca llamada makeGetRequest que toma en el punto final y la función de devolución de llamada, para que este código sea más limpio. Basta con hacerse con 3 elementos de la forma en que los resultados de ingenuos en este:

var success1 = function(elements){ 
    var success2 = function(elements){ 
     makeGetRequest("api/ListItems/3", finalSuccess); 
    } 
    makeGetRequest("api/ListItems/2", success2); 
} 
makeGetRequest("api/ListItems/1", success1); 

asqueroso! Este es el tipo de cosas en la programación 101 en las que nos golpean las muñecas y apuntan a los bucles. Pero, ¿cómo se puede hacer esto con un bucle, sin tener que depender del almacenamiento externo?

for(var i : values){ 
    makeGetRequest("api/ListItems/" + i, successFunction); 
} 

function successFunction(items){ 
    //I am called i-many times, each time only having ONE list's worth of items! 
} 

E incluso con el almacenamiento, tendría que saber cuándo todos han terminado y recuperar sus datos y llamar a alguna función principal que recupera todos los datos recogidos y hace algo con él.

¿Existe una práctica para manejar esto? Esto debe haber sido resuelto muchas veces antes ...

+0

JQuery $ .get y $ .each – mplungjan

+0

hay una razón por la que no tendría una ruta en su back-end para recuperar todo esto por usted, p. 'api/ListItems/all' o algo similar? entonces podrías evitar la necesidad de cualquier tipo de ciclo asincrónico. – jackwanders

Respuesta

4

Trate de usar una pila de parámetros de punto final:

var params = []; 
var results []; 

params.push({endpoint: "api/ListItems/1"}); 
params.push({endpoint: "api/ListItems/2"}); 
params.push({endpoint: "api/ListItems/3"}); 
params.push({endpoint: "api/ListItems/4"}); 

A continuación, puede hacer que sea recursiva en el controlador éxito:

function getResources(endPoint) { 

    var options = {} // Ajax Options 
    options.success = function (data) { 
     if (params.length > 0) { 
      results.push({endpoint: endpoint, data: data}); 
      getResources(params.shift().endpoint); 
     } 
     else { 
      theMasterFunction(results) 
     } 
    } 

    $.get(endPoint, options) 
} 

Y usted puede comenzar con una sola llamada así:

getResources(params.shift().endpoint); 

E DIT:

Para mantener todo independiente y fuera del ámbito global se puede utilizar una función y proporcionar una devolución de llamada:

function downloadResources(callback) { 

    var endpoints = []; 
    var results []; 

    endpoints.push({endpoint: "api/ListItems/1"}); 
    endpoints.push({endpoint: "api/ListItems/2"}); 
    endpoints.push({endpoint: "api/ListItems/3"}); 
    endpoints.push({endpoint: "api/ListItems/4"}); 

    function getResources(endPoint) { 
     var options = {} // Ajax Options 
     options.success = function (data) { 
      if (endpoints.length > 0) { 
       results.push({endpoint: endpoint, data: data}); 
       getResources(endpoints.shift().endpoint); 
      } 
      else { 
       callback(results) 
      } 
     } 
     $.get(endPoint, options) 
    } 

    getResources(endpoints.shift().endpoint); 

} 

En uso: Respuesta

downloadResources(function(data) { 
    // Do stuff with your data set 
}); 
+0

Cuando la iteración falla, ve a la recursión, ¿eh? ¡Una solución muy elegante! Todavía necesito encontrar un lugar para esconder 'params' y' results' para que no se salgan del alcance entre las llamadas, sin embargo. Alguna sugerencia? Intento evitar la trampa de la "variable global". –

+0

@ngmiceli Sugeriría una función DownloadResources que contenga la matriz de puntos finales, luego puede proporcionar su devolución de llamada continua como argumento para esta función. Ver mi edición para más detalles. – dmck

2

de dmck es probablemente su mejor apuesta. Sin embargo, otra opción es hacer una opción de lista masiva, para que su api admita solicitudes como api/ListItems /? Id = 1 & id = 2 & id = 3.

También podría hacer un punto final de búsqueda de API, si eso se ajusta más a su estética personal.

+0

Este es un buen punto, y una solución muy simple que pasé por alto por completo. Sigue muy bien con el comentario de @jackwanders. Dale a mi API la capacidad de manejar un GET masivo, y juntar todo junto en el lado del cliente. ¿Esto todavía se considera RESTful? –

+0

Si está recuperando datos con el protocolo GET, entonces no importa cuán "bonita" sea la URL, entonces es RESTful. Hay algunas dudas sobre cómo debería funcionar ese punto final. Usted lo llama una "lista", donde un nombre más apropiado podría ser la lista masiva o la búsqueda. – Jordan

Cuestiones relacionadas