【问题标题】:Trouble understanding how to use jquery Deferred/then with callbacks无法理解如何将 jquery Deferred/then 与回调一起使用
【发布时间】:2014-12-18 22:05:57
【问题描述】:

我当前的 javascript 代码基本上看起来像::

function doStep1(callback) {
  thirdPartyLib.asyncExec('step1', {}, function(resp) { 
     callback(resp.value); 
   });
}
function doStep2(value, callback) {
  thirdPartyLib.asyncExec('step2', value, function(resp) { 
     callback(resp.value); 
   }); 
}
function doStep3(value, callback) {
  thirdPartyLib.asyncExec('step3', value, function(resp) { 
     callback(resp.value); 
   }); 
}
function displayResult(value) {
  $('#input').enable();
  $('#result').text(value);
}

function run() {
   doStep1(function(x){doStep2(x,function(y){doStep3(y,displayResult)}});
}

也就是说,我们需要调用三个单独的异步函数,每个函数的结果都会传递给下一个函数。但是语法非常糟糕,即使在这个非常简化的版本中也是如此。我希望我可以使用 jquery 的 deferred/promises 支持之类的东西来编写更喜欢的东西:

$.when(doStep1).then(doStep2).then(doStep3).then(displayResult);

但显然这不是正确的语法,我不确定我是否真的理解我应该使用什么语法来实现这一点,因为我尝试过的所有内容最终看起来都比我上面的 run() 函数更复杂,这违背了目的。 为了踢球,我实际上编写了我自己的 'when' 和 'then' 版本,这将允许上述语法(你仍然必须调用,例如 'resolve' 或最后的其他东西才能实际进行调用,请注意),所以我知道这应该是可能的,但也许 jQuery 库不是为这种情况设计的?

【问题讨论】:

  • 这里使用“async”和“q”回答了类似的问题:stackoverflow.com/questions/23750280/…
  • 作为小类/插件:fiddle.
  • 并传递值:fiddle.
  • 令人印象深刻,这实际上确实工作得很好......但这确实意味着必须编写具有非常特殊签名的回调函数,我想知道它也会如何看待错误处理.非常感谢你,即使我还没有完全理解它。

标签: jquery asynchronous deferred


【解决方案1】:

有很多方法可以写这个。您所写的具体内容取决于未简化代码的性质。

让我们做一个假设:

所有第三方调用都具有足够相似的形式,可以概括 doStep()函数可写,可命令执行 任何步骤。

从表面上看简化的代码,那么这个假设就满足了,代码也相当简单:

function doStep(step, value) {
    return $.Deferred(function(dfrd) {
        thirdPartyLib.asyncExec(step, value, dfrd.resolve);
    }).then(function(resp) {
        return resp.value;
    });
}
function displayResult(value) {
    $('#input').enable();
    $('#result').text(value);
}
function run(steps) {
    return steps.reduce(function(promise, step) {
        return promise.then(function(value) {
            return doStep(step, value);
        });        
    }, $.when( {} ));// the empty object here becomes the `value` passed anongside 'step1'.
}

//The asychronous sequence is determined by an array passed to run()
run(['step1', 'step2', 'step3']);

如果每个第三方调用的形式不同,那么代码会更复杂,但可能还不算太糟糕。

【讨论】:

  • 它看起来很整洁,但我无法真正看到它在实际情况下如何工作,即每个 3rd 方库调用的参数传递和结果解析实际上是完全不同的。但这绝对可以帮助我更好地理解如何将值从一个函数传递到下一个函数,所以谢谢。
  • 上面的代码尽可能简洁。如果第 3 方库调用差异很大,则可以在保持“主管”run() 的中心主题的同时调整整体结构。您的第一个方法是在doStep() 中使用例如开关/代码结构进行分支。如果这还不够,您可以返回到单独的“doStepX”函数并安排run() 在每一步调用相应的函数。
  • 最后的手段是使用fn.bind()将参数绑定的函数数组传递给修改后的run()
  • 我应该说,Array.prototype.reduce 正在迅速成为从数据数组构建.then() 链的事实上的 解决方案。编写异步程序的人越来越多地熟悉这一点。顺便说一句,我没有发明它,我没那么聪明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-08
相关资源
最近更新 更多