2015-09-07 15 views
6

Come utilizzare $.when in JQuery con promesse concatenate per garantire che le richieste ajax vengano completate nell'ordine corretto?

Ho un array chiamato costArray che è composto da un numero di oggetti dinamici. Per ogni articolo di questo array, chiamerò una richiesta Ajax chiamata GetWorkOrder che restituisce un WorkOrder che è fondamentalmente un elemento di riga di tabella con la classe .workOrder e lo aggiunge alla tabella con ID #tbodyWorkOrders.

Dopo aver elaborato tutti gli elementi dell'array, utilizzare $.when per farmi sapere quando posso calcolare lo SubTotal di ogni WorkOrder.

Il mio problema è che i miei WorkOrder vengono inseriti in ordini casuali, poiché le richieste ajax sono in fase di elaborazione asincrona. Come posso garantire che le mie richieste di ajax vengano elaborate e aggiunte nell'ordine corretto?

i = 0; 

$.each(costArray, function (key, value) { 
var d1 = $.get('/WorkOrders/GetWorkOrder', { 'i': i }, function (html) { 
    $('#tbodyWorkOrders').append(html); 
    $('.workOrder').last().find('input').val(value.Subtotal); 
}); 

$.when(d1).done(function() { 
    SetSubtotal(); 
    i++; 
}); 

Edit:

costArray è tratto da una chiamata AJAX in precedenza ed è un array di oggetti che sto inserendo nel righe della tabella:

var costArray = JSON.parse([{"Trade":"Plasterer","Notes":"Test","Subtotal":"3781.00"}]); 

La linea:

$('.workOrder').last().find('input').val(value.Subtotal); 

è uno dei tanti che prende i valori da GetWorkOrder e li inserisce negli input corretti, ma Ho omesso il codice extra per chiarezza

+0

Prendere in considerazione l'inclusione di un intero che indica l'ordine nella chiusura della richiamata di successo. – bhspencer

risposta

4

$.when() elabora tutte le promesse passate in parallelo, non sequenziali (poiché le operazioni asincrone sono già state avviate prima ancora di arrivare a $.when()).

Raccoglierà i risultati per voi nell'ordine in cui si passano le promesse a $.when(), ma non vi è alcuna garanzia sull'ordine di esecuzione delle operazioni passate.

Quello che suggerirei è di raccogliere tutti i risultati (in ordine), quindi inserirli in ordine dopo averli completati.

Ho provato a ristrutturare il codice, ma non è chiaro quali elementi formano costArray che si desidera passare alla chiamata Ajax. Non stavi passando nulla da costArray nel tuo codice, ma il testo della tua domanda dice che dovresti esserlo. Quindi, in ogni caso, ecco un contorno strutturale per come questo potrebbe funzionare:

var promises = costArray.map(function (value, index) { 
    // Fix: you need to pass something from costArray to your ajax call here 
    return $.get('/WorkOrders/GetWorkOrder', { 'i': value }); 
}); 
$.when.apply($, promises).done(function() { 
    // all ajax calls are done here and are in order in the results array 
    // due to the wonders of jQuery, the results of the ajax call 
    // are in arguments[0][0], arguments[1][0], arguments[2][0], etc... 
    for (var i = 0; i < arguments.length; i++) { 
     var html = arguments[i][0]; 
     $('#tbodyWorkOrders').append(html); 
    } 
    SetSubtotal(); 
}); 
+0

Si prega di utilizzare una frase diversa da "' $ .when' elabora le operazioni " – Bergi

+0

@Berg - modificato. – jfriend00

+1

non pensare '$.quando 'prende array come argomento senza usare' apply() ' – charlietfl

1

avvolgerla in una funzione e richiamarlo dalla tua ajax successo:

ajax(0); 
function ajax(key) { 
    $.get('/WorkOrders/GetWorkOrder', {'i' : key }, 
     function (html) { 
      $('#tbodyWorkOrders').append(html); 
      $('.workOrder').last().find('input').val(costArray[key].Subtotal); 
      SetSubtotal(); 
      key++; 
      if (key < costArray.length) 
       ajax(key); 
     }); 
} 

Edit: Su ulteriore considerazione, mentre questo è un modo per farlo, implica che le chiamate ajax eseguano solo una alla volta, il che non è molto efficiente nel tempo. Vorrei andare con la risposta di jfreind00.

Problemi correlati