jquery - Onnistumisen käsittely mukautetussa JavaScript-funktiossa
Jos teen ajax-kutsun, voin lisätä onnistumisen käsittelyn. Haluan lisätä samanlaista logiikkaa omiin mukautettuihin toimintoihini.
Minulla on 6-10 mukautettua funktiota, jotka TÄYTYY suorittaa peräkkäin tai itsenäisesti. Ne eivät yleensä toimi itsenäisesti, joten olen nyt ketjuttanut ne siten, että seuraava funktio kutsutaan edellisen lopussa, mutta se on sotkuista lukea eikä salli erillistä suorittamista.
Haluaisin todella jotain tällaista:
function runall(){
runfirst().success(
runsecond().success(
runthird()
))
}
Minulla on ollut muita tilanteita, joissa haluaisin lisätä .success()-käsittelyn mukautettuun funktioon, mutta tämä tilanne teki siitä tärkeämpää.
Jos on toinen tapa pakottaa 6-10 funktiota suorittamaan synkronisesti, se voisi ratkaista tämän ongelman, mutta haluaisin myös tietää, miten lisätä onnistumisen käsittely omiin funktioihini.
Kokeilin seuraavaa @lanzz'n ehdotuksen perusteella:
Lisäsin funktiooni/funktioihini .then():
$bomImport.updateGridRow(rowId).then(function () {
$bomImport.toggleSubGrid(rowId, false);
});
var $bomImport = {
updateGridRow: function (rowId) {
$('#' + rowId + ' td[aria-describedby="bomImport_rev"]').html($("#mxRevTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_itemno"]').html($("#itemNoTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_used"]').html($("#usedTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_partSource"]').html($("#partSourceTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_partClass"]').html($("#partClassTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_partType"]').html($("#partTypeTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_partno"]').html($("#mxPnTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_descript"]').html($("#descTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_qty"]').html($("#qtyTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_custPartNo"]').html($("#custPartNoTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_crev"]').html($("#custRevTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_u_of_m"]').html($("#uomTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_warehouse"]').html($("#warehouseTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_standardCost"]').html($("#stdCostTxt").val());
$('#' + rowId + ' td[aria-describedby="bomImport_workCenter"]').html($("#wcTxt").val());
var defferred = new $.Deferred();
return defferred.promise();
}};
Koodi menee oikein updateGridRowin loppuun, ei anna virheitä, mutta ei koskaan palaa kutsumaan toista funktiota.
Kokeilin myös seuraavaa, kuten Anand ehdotti:
workSheetSaveExit(rowId, isNew).save().updateRow().toggle();
function workSheetSaveExit(){
this.queue = new Queue;
var self = this;
self.queue.flush(this);
}
workSheetSaveExit.prototype = {
save: function () {
this.queue.add(function (self) {
$bomImport.workSheetSave(rowId, isNew);
});
return this;
},
updateRow: function () {
this.queue.add(function (self) {
$bomImport.updateGridRow(rowId);
});
return this;
},
toggle: function () {
this.queue.add(function (self) {
$bomImport.toggleSubGrid(rowId, false);
});
return this;
}
};
Mikä ei toiminut.
Lopullinen ratkaisu
Hienoon selitykseen siitä, miten käyttää deferredia ja saada tämä toimimaan, katso tästä: Using Deferred in jQuery
Vastaus #1
Kuinka käyttää Deferred-objekteja:
function somethingAsynchronous() {
var deferred = new $.Deferred();
// now, delay the resolution of the deferred:
setTimeout(function() {
deferred.resolve('foobar');
}, 2000);
return deferred.promise();
}
somethingAsynchronous().then(function(result) {
// result is "foobar", as provided by deferred.resolve() in somethingAsynchronous()
alert('after somethingAsynchronous(): ' + result);
});
// or, you can also use $.when() to wait on multiple deferreds:
$.when(somethingAsynchronous(), $.ajax({ something })).then(function() {
alert('after BOTH somethingAsynchronous() and $.ajax()');
});
Jos funktiosi tekevät vain AJAX-pyynnön, voit yksinkertaisesti palauttaa varsinaisen $.ajax() -funktion palauttaman promisen:
function doAjax() {
return $.ajax({ /* ajax options */ });
}
doAjax().then(function() {
alert('after doAjax()');
});
Vastaus #2
Siitä mitä voin kertoa, haluat oikeastaan vain paremman tavan järjestää nämä palautukset. Sinun pitäisi käyttää FIFO-taulukkoa tai jonoa. Run all -toimintosi pitäisi hoitaa pinoamisen puolestasi ja sitten suorittaa ensimmäinen funktio.
var RunQueue = function(queue){
this.init(queue);
}
var p = RunQueue.prototype = {};
p.queue = null;
p.init = function(queue){
this.queue = queue.slice(); //copy the array we will be changing it
// if this is not practical, keep an index
}
p.run = function(){
if(this.queue && this.queue.length) {
var first = this.queue[0];
this.queue.shift();
var runQueue = this;
first(function(){ /*success callback parameter*/
runQueue.run();
});
}
}
Käyttö :
var queue = [runFirst, runSecond, runThird, ...]
(new RunQueue(queue)).run();
Jos todella haluat tehdä monimutkaisempaa, ja saatat tarvita sitä, voit välittää taulukossa olevia Objekteja, jotka sisältävät parametrit, ja antaa RunQueue:n lisätä viimeisen parametrin onnistumisen takaisinsoittona. Voit jopa välittää kontekstin suorittaaksesi funktion siinä objektissa ja sitten kutsua apply- tai call-metodia (kumpaa tahansa, joka käyttää taulukkoa) metodissasi.
{
method: runFirst,
context: someObject,
parameters: [param1, param2, param3];
}
