2015-09-07 12 views
6

Wie verwende ich $.when in JQuery mit verketteten Versprechen, um sicherzustellen, dass meine Ajax-Anfragen in der richtigen Reihenfolge abgeschlossen werden?

Ich habe ein Array namens costArray, die aus einer Reihe von dynamischen Objekten besteht. Für jedes Element in diesem Array werde ich eine Ajax-Anfrage mit dem Namen GetWorkOrder aufrufen, die eine WorkOrder zurückgibt, die im Grunde ein Tabellenzeilenelement mit der Klasse .workOrder ist und es an die Tabelle mit der ID #tbodyWorkOrders anfügt.

Sobald alle Elemente im Array verarbeitet sind, verwende ich $.when, um mich wissen zu lassen, wenn ich die SubTotal von jedem WorkOrder berechnen kann.

Mein Problem ist, dass meine WorkOrder s in zufälligen Reihenfolgen eingefügt werden, da die Ajax-Anfragen async verarbeitet werden. Wie kann ich sicherstellen, dass meine Ajax-Anfragen in der richtigen Reihenfolge bearbeitet und angehängt werden?

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 aus einem frühen Ajax-Aufruf genommen und ist ein Array von Elementen, die ich in die Tabellenzeilen am Einfügen:

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

Die Linie:

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

ist einer von vielen, die die Werte von GetWorkOrder nimmt und sie in die richtigen Eingaben setzt, aber Ich habe den zusätzlichen Code für Klarheit weggelassen

+0

Sie können eine Ganzzahl angeben, die die Reihenfolge beim Schließen des Erfolgsrückrufs angibt. – bhspencer

Antwort

4

$.when() verarbeitet alle Versprechen, die Sie übergeben es parallel, nicht sequentiell (da die asynchronen Operationen bereits gestartet wurden, bevor Sie sogar $.when() erreichen).

Es sammelt die Ergebnisse für Sie in der Reihenfolge, in der Sie die Versprechen an $.when() übergeben, aber es gibt keine Garantie über die Ausführungsreihenfolge der Operationen, die an es übergeben werden.

Was ich vorschlagen würde ist, dass Sie alle Ergebnisse (in der Reihenfolge) sammeln, dann fügen Sie sie in der Reihenfolge, nachdem sie alle fertig sind.

Ich habe versucht, Ihren Code zu restrukturieren, aber es ist nicht klar, welche Elemente costArray Sie zu Ihrem Ajax Anruf übergeben möchten. Sie haben nichts aus costArray in Ihrem Code übergeben, aber der Text Ihrer Frage sagt, dass Sie sein sollten. Also, wie auch immer, hier ist eine strukturelle Gliederung für, wie dies funktionieren könnte:

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

Bitte verwenden Sie eine andere Formulierung von "$ .when" verarbeitet die Operationen " – Bergi

+0

@Bergi - geändert. – jfriend00

+1

denke nicht '$.when' nimmt Array als Argument ohne Verwendung von 'apply()' – charlietfl

1

Wickeln Sie es in einer Funktion und rufen Sie sie von Ihrem Ajax-Erfolg:

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: Bei näherer Betrachtung, während Dies ist eine Möglichkeit, es zu tun, es beinhaltet die Ajax-Aufrufe, die jeweils nur einzeln ausgeführt werden, was nicht sehr zeiteffizient ist. Ich würde mit jfreind00's Antwort gehen.

Verwandte Themen