6

如果我进行 ajax 调用,我可以添加成功处理。我想为我的自定义函数添加类似的逻辑。

我有 6-10 个必须按顺序或独立运行的自定义函数。它们通常不会独立运行,因此我现在通过在前一个函数的末尾调用下一个函数将它们以菊花链形式连接起来,但这读起来很麻烦,并且不允许单独执行。

我很想拥有这样的东西:

function runall(){
    runfirst().success(
        runsecond().success(
            runthird()
    ))
} 

我有过其他情况,我想为.success()自定义函数添加处理,但这种情况使它变得更加重要。

如果有另一种方法可以强制 6-10 个函数同步运行,那可以解决这个问题,但我也想知道如何将成功处理添加到我的自定义函数中。

我根据@lanzz 的建议尝试了以下方法:

我添加.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();
}};

代码正确地转到 updateGridRow 的末尾,没有给出错误,但永远不会返回调用第二个函数。

我还按照@Anand 的建议尝试了以下操作:

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;
  }
};

这没有用。

最终解决方案
有关如何使用 deferred 并使其工作的详细说明,请参见此处: 在 jQuery 中使用 Deferred

4

3 回答 3

5

如何使用延迟

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()');
});

如果您的函数只是发出 AJAX 请求,您可以只返回由返回的实际承诺$.ajax()

function doAjax() {
    return $.ajax({ /* ajax options */ });
}

doAjax().then(function() {
    alert('after doAjax()');
});
于 2012-06-19T15:58:10.480 回答
0

如果您的每个函数都返回一个状态/函数,然后您可能可以为每个状态/函数添加一个原型,那么您将能够以流利的 api 方式(方法链接)调用这样的函数。

runfirst().runSecond().runThird() 

等等。

让我试着建立一个样本。

编辑

看看这个,如果它适合你的设计

编辑 2 我没有意识到,你在谈论异步方法链接。这里有很好的例子。在这个stackoverflow线程中讨论过

于 2012-06-19T11:35:34.817 回答
0

据我所知,你真的只是想要一种更好的方式来组织这些回调。您应该使用 FIFO 数组或队列。你的 run all 应该为你做你的堆叠,然后执行第一个函数。

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();
        });
    }
}

用法:

var queue = [runFirst, runSecond, runThird, ...]

(new RunQueue(queue)).run();

如果您真的想要花哨,并且您可能需要,您可以在包含您的参数的数组中传入 Objects,并让 RunQueue 将最后一个参数附加为成功回调。您甚至可以传入上下文以在该对象中运行函数,然后在您的方法上调用 apply 或 call(无论哪个使用数组)。

{
    method: runFirst,
    context: someObject,
    parameters: [param1, param2, param3];
}
于 2012-06-19T12:27:48.737 回答