jquery espera todas las paginaciones -- javascript campo con jquery campo con asynchronous campo con promise campo con pagination camp codereview Relacionados El problema

jQuery wait for all paginations


3
vote

problema

Español

Quiero descargar datos para todos de mis reposs de la API de GitHub.

GitHub pagina sus respuestas e incluye un encabezado std::priority_queue0 cuando hay otra página disponible. Así que sé que quiero esperar a que se reciban todas las páginas ... pero no sé inicialmente cuántas páginas habrá, y no sé si hay un siguiente Página hasta la anterior, entra.

hasta ahora tengo esto, y funciona:

  std::priority_queue1  

La razón por la que utilizo el 998877666555443312 El 99887766555443313 se resolverá antes de que la devolución de llamada presione la nueva promesa de 998877766655443314 en la matriz PROMESEY.

¿Hay una mejor manera de hacer / resolver este tipo de cadena de "desenredar"?

Original en ingles

I want to download data for all of my repos from the Github API.

Github paginates their responses and includes a header Link type:"next" when there's another page available. So I know I want to wait for all the pages to be received... but I don't know initially how many pages there are going to be, and I don't know if there's a next page until the one before it comes in.

So far I've got this, and it works:

var allRepos = []; var repoPageReqs = [$.Deferred()]; // <-- sketchy function receivedReposPage(data, status, req) {      //handle error inadequately but whatever for now     if (status !== "success") { console.log(data, status, req); return; }      console.log("Received repos from Github:", data);     for (i in data) {         allRepos.push(data[i]);     }     saveRepos(allRepos);      var headerLink = req.getResponseHeader("Link");     var headerLinkNext = parseLinkHeader(headerLink)["next"];     if (headerLinkNext) {         console.log("Following 'next' header link, collecting paginated repos.");         repoPageReqs.push(downloadRepos(headerLinkNext));     } else {         repoPageReqs[0].resolve(); // <-- resolve sketchiness     } }  function downloadRepos(path) {     return $.get(path, receivedReposPage); }  function downloadAllRepos(path) {     repoPageReqs.push(downloadRepos(path));     return $.when.apply(null, repoPageReqs); }  $(function () {     downloadAllRepos("https://api.github.com/my/repos/path")       .then(function () {            console.log("finished downloading all repos");       }) }); 

The reason I use the sketchy [$.Deferred()] was because the $.when would resolve before the callback pushed the new $.get promise into the promisey array.

Is there a better way to make/resolve this kind of "unraveling" chain?

              

Lista de respuestas

1
 
vote
vote
La mejor respuesta
 

Uso de $.when es útil cuando sabe que tiene n operaciones asíncronas que tienen que resolver. Sin embargo, en este caso, como usted dice, no sepa cuántos habrá, por lo que lo más sencillo sería crear una promesa "maestra" / Deferred y resolver eso en el apropiado tiempo.

¿Cuál es básicamente lo que ya está haciendo con ese 9988777665544335 , simplemente lo encuentra mezclado en una matriz e insistiendo en todo este $.when cosas que no son útiles Aquí.

Pero primero, algunas cosas pequeñas:

  • TIENE i Como una variable global implícita en su for(i in data) - Eso es un NO-NO.

  • También estoy desconfiado del parseLinkHeader(headerLink)["next"] linea. Para uno, también podría ser /** * Formats dates to specific time formats. * @interface */ function ITimeFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatTimeString = function(dateObject) {} } /** * Formats dates to specific date formats. * @interface */ function IDateFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatDateString = function(dateObject) {} } /** * Formats dates to standard time format. * @implements ITimeFormatter */ function StandardTimeFormatter() { this.formatTimeString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toLocaleTimeString(); } } /** * Formats dates to standard date format. * @implements IDateFormatter */ function StandardDateFormatter() { this.formatDateString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toDateString(); } } function showDateAndTime() { document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date()); document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); } setInterval(showDateAndTime, 1000); 0 en lugar de la notación del soporte, pero lo más importante es que es seguro asumir que /** * Formats dates to specific time formats. * @interface */ function ITimeFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatTimeString = function(dateObject) {} } /** * Formats dates to specific date formats. * @interface */ function IDateFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatDateString = function(dateObject) {} } /** * Formats dates to standard time format. * @implements ITimeFormatter */ function StandardTimeFormatter() { this.formatTimeString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toLocaleTimeString(); } } /** * Formats dates to standard date format. * @implements IDateFormatter */ function StandardDateFormatter() { this.formatDateString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toDateString(); } } function showDateAndTime() { document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date()); document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); } setInterval(showDateAndTime, 1000); 1 siempre devolverá un objeto? Si falla, preferiría que devuelva /** * Formats dates to specific time formats. * @interface */ function ITimeFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatTimeString = function(dateObject) {} } /** * Formats dates to specific date formats. * @interface */ function IDateFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatDateString = function(dateObject) {} } /** * Formats dates to standard time format. * @implements ITimeFormatter */ function StandardTimeFormatter() { this.formatTimeString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toLocaleTimeString(); } } /** * Formats dates to standard date format. * @implements IDateFormatter */ function StandardDateFormatter() { this.formatDateString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toDateString(); } } function showDateAndTime() { document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date()); document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); } setInterval(showDateAndTime, 1000); 2 o /** * Formats dates to specific time formats. * @interface */ function ITimeFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatTimeString = function(dateObject) {} } /** * Formats dates to specific date formats. * @interface */ function IDateFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatDateString = function(dateObject) {} } /** * Formats dates to standard time format. * @implements ITimeFormatter */ function StandardTimeFormatter() { this.formatTimeString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toLocaleTimeString(); } } /** * Formats dates to standard date format. * @implements IDateFormatter */ function StandardDateFormatter() { this.formatDateString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toDateString(); } } function showDateAndTime() { document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date()); document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); } setInterval(showDateAndTime, 1000); 3 , pero luego el código fallará al intentar algo como /** * Formats dates to specific time formats. * @interface */ function ITimeFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatTimeString = function(dateObject) {} } /** * Formats dates to specific date formats. * @interface */ function IDateFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatDateString = function(dateObject) {} } /** * Formats dates to standard time format. * @implements ITimeFormatter */ function StandardTimeFormatter() { this.formatTimeString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toLocaleTimeString(); } } /** * Formats dates to standard date format. * @implements IDateFormatter */ function StandardDateFormatter() { this.formatDateString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toDateString(); } } function showDateAndTime() { document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date()); document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); } setInterval(showDateAndTime, 1000); 4 .

    No sabría cómo funciona su función 99887766555443315 , pero simplemente me huele un poco extraño.

De todos modos, el punto es usar una única promesa "general", en lugar de todo ese /** * Formats dates to specific time formats. * @interface */ function ITimeFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatTimeString = function(dateObject) {} } /** * Formats dates to specific date formats. * @interface */ function IDateFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatDateString = function(dateObject) {} } /** * Formats dates to standard time format. * @implements ITimeFormatter */ function StandardTimeFormatter() { this.formatTimeString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toLocaleTimeString(); } } /** * Formats dates to standard date format. * @implements IDateFormatter */ function StandardDateFormatter() { this.formatDateString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toDateString(); } } function showDateAndTime() { document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date()); document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); } setInterval(showDateAndTime, 1000); 6 cosas. Algo así como:

  /**  * Formats dates to specific time formats.  * @interface  */ function ITimeFormatter() {     /**      * @param {Date} dateObject      * @return {string}      */     this.formatTimeString = function(dateObject) {} }  /**  * Formats dates to specific date formats.  * @interface  */ function IDateFormatter() {     /**      * @param {Date} dateObject      * @return {string}      */     this.formatDateString = function(dateObject) {} }   /**  * Formats dates to standard time format.  * @implements ITimeFormatter  */ function StandardTimeFormatter() {     this.formatTimeString = function(dateObject) {         dateObject = dateObject || new Date;         return dateObject.toLocaleTimeString();     } }  /**  * Formats dates to standard date format.  * @implements IDateFormatter  */ function StandardDateFormatter() {     this.formatDateString = function(dateObject) {         dateObject = dateObject || new Date;         return dateObject.toDateString();     } }  function showDateAndTime() {     document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date());       document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); }   setInterval(showDateAndTime, 1000); 7  

He colocado todo dentro de la función /** * Formats dates to specific time formats. * @interface */ function ITimeFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatTimeString = function(dateObject) {} } /** * Formats dates to specific date formats. * @interface */ function IDateFormatter() { /** * @param {Date} dateObject * @return {string} */ this.formatDateString = function(dateObject) {} } /** * Formats dates to standard time format. * @implements ITimeFormatter */ function StandardTimeFormatter() { this.formatTimeString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toLocaleTimeString(); } } /** * Formats dates to standard date format. * @implements IDateFormatter */ function StandardDateFormatter() { this.formatDateString = function(dateObject) { dateObject = dateObject || new Date; return dateObject.toDateString(); } } function showDateAndTime() { document.getElementById('js-date').innerHTML = (new StandardDateFormatter()).formatDateString(new Date()); document.getElementById('js-time').innerHTML = (new StandardTimeFormatter()).formatTimeString(new Date()); } setInterval(showDateAndTime, 1000); 8 para reducir la huella general.

 

Using $.when is useful when you know you have N asynchronous operations that have to resolve. However, in this case you, as you say, don't know how many there'll be, so the simpler thing would be to create one "master" promise/Deferred and resolve that at the appropriate time.

Which is basically what you're already doing with that repoPageReqs[0] promise, you just have it mixed up in an array and insisting on all this $.when stuff that's not useful here.

But first, some small stuff:

  • You have i as an implied global variable in your for(i in data) - that's a no-no.

  • I'm also wary of the parseLinkHeader(headerLink)["next"] line. For one, it might as well be .next instead of the bracket notation, but more importantly, is it safe to assume that parseLinkHeader will always return an object? If it fails, I'd rather have it return null or undefined, but then the code will fail when trying something like null["next"].

    I'd don't know how your parseLinkHeader function works, but it just smells a little strange to me.

Anyway, point is to use a single "overall" promise, instead of all that $.when stuff. Something like:

function downloadAllRepos(path) {   var deferred = $.Deferred(), // the "master" promise       repos = [];    function parseLinkHeader(header) { ... }    function receivedReposPage(data, status, req) {     if (status !== 'success') {       deferred.reject(data, status, req); // reject the promise if any page fails to load       return;     }      // if data is an array, then you should *not* use a for..in loop     // but a regular for loop instead.  for..in is made to iterate     // object properties, not array elements. Calling the counter var     // i makes me think you're dealing with an array... but I don't     // know what the data variable is, so I've kept the for..in loop     // and the assumption that it's an object rather than an array,     // but added a sanity check to skip over any inherited properties     // that might otherwise get erroneously iterated.     // (And if data is an array, you might get away with simply     // saying `repos = repos.concat(data)` instead of looping!)     for (var prop in data) {       if (!data.hasOwnProperty(prop)) continue;       allRepos.push(data[prop]);     }      // you may want to call deferred.notify() here to let     // others know that you've downloaded another page, e.g.     // you could send the number of repos gotten so far:     deferred.notify(repos.length);      // a slightly safer approach to getting/parsing the header     var linkHeader = parseLinkHeader(req.getResponseHeader('Link'));     if (linkHeader && linkHeader.next) {       getPage(linkHeader.next); // get the next page     } else {       deferred.resolve(repos); // all done, resolve the promise     }   }    function getPage(path) {     $.get(path, receivedReposPage);   }    // get the first page   getPage(path);    // return a promise   return deferred.promise(); }  // Example downloadAllRepos("https://api.github.com/my/repos/path")   .progress(function (repoCount) {     console.log("Downloaded " + repoCount + " repo(s) so far...");   })   .success(function (repos) {     // code to run when *all* pages have loaded   })   .failure(function (data, status, req) {     // code to run if a page failed to load     console.log(data, status, req);   }); 

I've placed everything inside the downloadAllRepos() function to reduce the overall footprint.

 
 
         
         

Relacionados problema

7  Versión de C # StringBuilder para permitir cadenas mayores de 2 mil millones de caracteres  ( Version of c stringbuilder to allow for strings larger than 2 billion character ) 
En las ventanas C #, 64bit, .NET 4.5 (o posterior) y habilitando gcAllowVeryLargeObjects en el archivo App.config permite objetos mayores de dos gigabytes. ...

5  Función PHP de la paginación: ¿puede este código ser hecho más eficiente?  ( Pagination php function can this code be made more efficient ) 
En primer lugar, no escribí este código desde cero, estoy bastante seguro de que lo tomé de un tutorial en línea y lo modificé ligeramente para satisfacer mis...

7  Plugin de paginación  ( Pagination plugin ) 
Este complemento está escrito en jQuery y se hace para admitir el marco de CodeIgniter . Es un complemento de paginación de tabla de AJAX diseñada para propo...

8  Paginando grandes resultados de SQL  ( Paginating large sql results ) 
Se siente como la paginación es una de las preguntas más discutidas en la web, que siempre termina con algunos hacks rápidos y sucios sobre cómo pagarse. Quie...

5  Paginación de Laravel con fórmula haversina en ella  ( Laravel pagination with haversine formula in it ) 
Estoy usando la fórmula de Haversine para contar la distancia del código postal seleccionado al destino deseado. Tengo el siguiente scope en AppModelsBus...

3  Filtrado de paginación  ( Pagination filtering ) 
Quiero verificar si hay variable de página (en URL) y, si es, si es correcto, no puede ser el número 1 porque esta es una página predeterminada y debe ser v...

1  Paginación con datos estáticos  ( Pagination with static data ) 
Estoy usando el siguiente código para implementar la funcionalidad de paginación. Todos los artículos están procesados ​​en la carga de la página y seconds::...

8  Transmisión de páginas de un tamaño diferente a las páginas de un caché  ( Streaming pages of a different size than a caches pages ) 
Necesito escribir un servicio para devolver objetos en las páginas del tamaño 20. El almacenamiento en caché de estos objetos se realiza en páginas de tamaño ...

2  Función para filtrar comentarios y calificaciones, con soporte de paginación  ( Function to filter comments and ratings with pagination support ) 
Tengo un componente web que está haciendo una lista de elementos y tengo este método para filtrar estos elementos basados ​​en un objeto 998877666554433320 ...

8  Paginación infinita de desplazamiento con un diseño de Wookmark  ( Infinite scroll pagination with a wookmark layout ) 
class ProgramssController < ApplicationController def index @programs = Program.paginate :page => params[:page], :per_page => params[:per_page] || 30 ...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos