【问题标题】:Chaining multiple callbacks to a single jquery promise将多个回调链接到单个 jquery 承诺
【发布时间】:2015-07-02 04:59:42
【问题描述】:

我有以下设置,我很好奇这是否是正确的方法。它工作正常,但我只是确保我做对了,或者是否有更好的方法来完成相同的任务。

//custom ajax wrapper
var pageLoadPromise = ajax({
    url: //call to webmethod
});

//this is the way I have been doing it
pageLoadPromise.done(cB1)
    .done(cB2)
    .done(cB3)
    .done(cB4)
    .done(function(){cB5(args);});
    //this function requires that cB1 has been completed

//I tried this and it worked as well
pageLoadPromise.done(cB1,cB2,cB3,cB4)
    .done(function(){cB5(agrs)});

两种方式都可以,但就像我说的,我想知道这是否是实现此目的的正确方法?

更新:

我对我的代码进行了小幅调整,特别是针对cB1 和对cB5 的回调

pageloadPromise.done(
    function(data){
        cB1(data).done(function(){
            cB5(args);
        });
     },cB2,cB3,cB4
 );

 function cB1(data){
     var cB1Promise = $.Deferred();
     ...

     cB1Promise.resolve();
     return cB1Promise;
 }

【问题讨论】:

  • @Asad 没有回调返回任何数据,但我将 data 对象传递给前 4 个 callbaks。
  • @Asad:不。.done 不是.then
  • @RobM:为什么会有 5 个不同的回调等待相同的数据?
  • @Bergi 前 4 个回调使用从 web 方法返回的不同数据。所以在页面加载时,我正在检索初始化页面所需的大量数据。该数据然后返回到一个json。在那个实际的回调中,我做了这样的事情:var cb1data= data.d.cb1data;。所以他们并不是都在等待相同的数据。

标签: javascript jquery promise


【解决方案1】:

更新。感谢@Bergi,他指出jQuery 的done() 实际上返回了相同的承诺。我已经基于此更新了答案。

如果cB2,cB3,cB4 没有互连,并且它们都处理来自 ajax 调用的相同数据,那么您可以将它们添加到相同的 Promise (pageloadPromise)。

考虑到上述假设,您的第二个版本的代码可以被简化,而无需在 cB1() 中创建新的承诺,也无需额外的缩进级别:

pageloadPromise.then(cB1).done(cB5);
pageloadPromise.done(cB2, cB3, cB4);

function cB1(data){
    // ...     
    //data2 would be the argument value passed when resolving
    // your original cB1Promise
    return data2; 
}

这里发生的情况是 .then() 调用创建了一个新的 Promise,该 Promise 将使用 cB1 返回的任何数据解析,允许 cB5 接收该数据而无需创建额外的回调并且不涉及另一个 Promise(因为我们已经有一个)。

但是,如果 cB1 需要另一个 ajax,那么您对 ​​cB1 的原始实现会更合适(但回调调度保持不变)。

最后一点,我没有注意到任何失败处理程序,以防 ajax 调用失败。

【讨论】:

  • 我的错,我认为 jQuery 承诺按照书本行事,并在什么时候返回一个新的承诺。感谢您指出这一点,将更新我的答案
【解决方案2】:

双管齐下

是的,它们几乎是等价的(.done(function(){cB5}); 除外,它不起作用)。

我想知道这是否是完成此任务的正确方法?

使用你更喜欢的那个。这更像是一个设计问题,而不是“正确性”问题。然而,这两种方式在我看来都很奇怪,而且我见过很多承诺代码。我会推荐两种不同的结构,具体取决于您的应用的结构:

  • 您使用pageLoadPromise 作为初始数据的全局缓存。然后,它在非常不同的地方,可能在不同的时间,用于多种不同的事物(或者甚至可能重复地用于同一事物)。然后在每个模块中重复使用pageLoadPromise

    var pageLoadPromise = ajax({url: …}); // initialisation 
    
    pageLoadPromise.done(cB1); // somewhere
    
    …
    pageLoadPromise.done(cB2); // somewhere else
    
    …
    pageLoadPromise.done(cB3); // other place or time
    
    …
    
  • 你只在一个地方使用pageLoadPromise,并且想在它加载时基本上做一件事,除了它是由多个子任务构成的;每个只需要一部分,而不是整个结构。然后只使用一个回调:

    ajax({url: …}).then(function(data) {
        cb1(data.d.cb1data);
        cb2(data.d.cb2data);
        cb3(data.d.cb3data);
        cb4(data.d.cb4data);
        cb5(data.d.cb5data, some_additional_data);
    });
    

我对我的代码做了一个小的调整,特别是针对cB1 和对cB5 的回调

cb1 不做任何异步操作时,你不应该让它返回一个承诺。不要修改它。如果你想明确表示cb5需要用cb1的结果执行,那么你应该使用.then进行链接:

var pageLoadPromise = ajax({url: …}); // initialisation 

var cB1promise = pageLoadPromise.then(cB1);

cB1promise.done(cb5); // does get called with the return value of cB1

ajax({url: …}).then(function(data) {
    var res1 = cb1(data.d.cb1data);
    …
    cb5(data.d.cb5data, some_additional_data, res1);
});

【讨论】:

  • 我喜欢第一种方法,但我的应用程序的结构并非如此。另外,在我的情况下,我看不出使用 .done.then 有什么区别。
  • 在您的情况下,没有区别,因为您的回调不返回任何内容,并且没有任何内容取决于它们的结果。
【解决方案3】:

正如@Bergi 所指出的,无论您如何添加回调,它们都按照使用done 附加的顺序运行。所以,promise.done(cb1, cb2, cb3, cb4).done(cb5)promise.done(cb1).done(cb2).done(cb3).done(cb4).done(cb5) 相同。

为了确保cb5cb1 之后运行,请使用:

promise.done( function(data) {cb1(data).done(cb5);}, cb2, cb3, cb4);

如果不需要,请删除data

我玩过http://jsbin.com/moqiko/4/edit?js,console,output中的场景

【讨论】:

  • 你的回答没有意义。无论它们如何附加,回调总是按顺序执行。如果其中一个依赖于另一个的结果,则无论如何都应该使用then 而不是done
  • @Bergi cb5只要求cb1在执行前完成,所以不需要任何数据,但要求执行完毕
  • @Bergi,你是对的。我误解了。这些都是等价的。 promise.done(cb1).done(cb2).done(cb3).done(cb4).done(cb5)promise.done(cb1, cb2, cb3, cb4, cb5), promise.done(cb1, cb2, cb3, cb4).done(cb5)`我会更新我的答案。
  • 这些回调都没有返回一个承诺,所以我怎么能cb1.done(...) 而不在每个函数中创建一个新的承诺对象。我在我的应用程序中对此进行了测试,但没有成功。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 2016-12-30
  • 1970-01-01
  • 2023-03-18
  • 2016-07-23
  • 2018-07-26
相关资源
最近更新 更多