2015-12-28 12 views
2

想我能得到($.ajax),过程(process_*)并保存(store_* =)数据AB独立,已经有API:API设计:如何组合两个延迟jQuery对象的结果?

var store_A; 
function A() { 
    $.ajax({url: "/getA"}).done(function(data) { 
    store_A = process_A(data); 
}); } 

var store_B; 
function B() { 
    $.ajax({url: "/getB"}).done(function(data) { 
    store_B = process_B(data); 
}); } 

我有一个函数C()是能够store_Astore_B结合成东西:

var store_C; 
function C() { 
    store_C = process_C(store_A, store_B); 
} 

假设A()B()C()是公开的API和一个其他东西是内部和实际复杂的代码(例如,我不能直接链接$.ajax)。

我想通过使用jQuery Deferred API,所以我可以请求任何情况下重构上面的代码到新的API:

case1: after(A).do(C) 
case1: after(B).do(C) 
case2: afterParallelJobsFinished(A, B).do(C) 

,并确保由于只有一个或两个的更新后要求和store_C更新store_Astore_B更新的A/B按要求。


想象我们有webapp哪里用户管理收入和费用的设置。

在页面加载,我们得到的收入和支出从不同的数据源(即$.ajax)并行,渲染视图和存储数据(通常被混合process_*/store_* =),并显示total = SUM(incomes) - SUM(expenses)当所有数据到达

那就是case2

当用户编辑费用并请求部分页面更新时,我们在case1因为我们只需要加载/渲染/存储扩展以获得正确的total = SUM(incomes) - SUM(expenses)

+0

您可以使用$ .when,但需要将承诺存储在store_X中。 – jcubic

+0

从两个独立的'.ajax()'我得到两个承诺。我怎样才能把它们结合起来我想保留独立运行'A()'或'B()'或'C()'的能力。 – gavenkoa

回答

3

$.when()可以接受任意数量的延迟对象。 It can even take a dynamic number如果你不知道你会打多少电话。

$.when(callA(), callB()).done(function() { 
// Do stuff here when both calls are done 
}); 

function callA() { 
    return $.ajax({ 
    url: ..., 
    success: function() { 
     // Do stuff here when callA is done 
    } 
    }); 
} 

function callB() { 
    return $.ajax({ 
    url: ..., 
    success: function() { 
     // Do stuff here when callB is done 
    } 
    }); 
} 
+0

不错!我可以使用'return $ .ajax()。done(...)'语法来代替'return $ .ajax({success:...})'吗?它们是否相同? – gavenkoa

+1

不,不一样。当他们中的一个完成时,你不希望“完成” - 只有当它们全部完成时。 –

+0

谢谢。我认为我的问题大多是因为“完成”与“成功”的误解。 – gavenkoa

0

现在,当我熟悉jQuery.Deffered API我想添加一些更多的自我表达的例子:

function callA() { 
    return $.ajax({ url: ... }) 
    .done(function(data) { successA(data); }) 
    .fail(function(data) { failA(data); }); 
} 

function callB() { 
    var promise1 = $.ajax({ url: ... }) 
    .done(function(data) { succB_1(data); }) 
    .fail(function(data) { failB_1(data); }); 
    var promise2 = $.ajax({ url: ... }) 
    .done(function(data) { succB_2(data); }) 
    .fail(function(data) { failB_2(data); }); 
    return $.when(promise1, promise2) 
    .done(function(data1, data2) { succCombined(data1, data2); }) 
    .fail(function(data1, data2) { failCombined(data1, data2); }); 
} 

$.when(callA(), callB()).done(function() { 
// Do stuff here when both calls are done 
}); 

注意里面callA/callB我用data/data1/data2,因为我知道内部API协议。在最后几行我不指望callA/callB返回一些合理的。但是,如果我添加公共API来callA/callB我可以使用:

$.when(callA(), callB()).done(function(resultA, resultB) { 
// Do stuff here when both calls are done 
}); 
2

这是马修·赫布斯特的回答坚持只是为了答应逻辑的修改。这避免了混合Promise逻辑和ajax回调的不必要的混淆。

$.when(callA(), callB()).done(function() { 
    // Do stuff here when both .then()'s are complete 
}); 

function callA() { 
    return $.ajax({ 
     url: ..., 
    }).then(function(result){ 
     // Do something when callA finishes 
     return result; 
    }); 
} 

function callB() { 
    return $.ajax({ 
     url: ..., 
    }).then(function(result){ 
     // Do something when callB finishes 
     return result; 
    }); 
}