在jQuery中,如何组合异步调用,包括json和jsonp

时间:2013-06-26 20:33:09

标签: jquery asynchronous jquery-deferred promise

我正在尝试使用jQuery调用三个服务。前两个获取数据,第三个使用数据进行更新。

第一部分:我想获取银行账户信息:

  • 来自Foo Bank,我想查看
  • 来自Bar Bank,我希望得到我的积蓄

第二部分:当我成功从两家银行获取信息后,我想将其上传到我自己服务的个人支票簿上。

这是一些看起来像Javascript的伪代码。如果我可以编写同步代码来完成工作,那就是我要写的东西,我知道我不能。

--PSEUDO CODE

var go = function () {
    var acctId;

    acctId = 12345;
    var myInfo = getAccounts(acctId);
    updateCheckbook(myInfo);
}

var getAccounts = function(acctId){
    var myInfo;

    myInfo = {
        id: acctId,
        fooDollars: GetFooBank(acctId),
        barDollars: GetBarBank(acctId)
    };

    return myInfo;
}

var updateCheckbook(myInfo){
    $.post('http://mySite.com/checkbook/', myInfo);
}

//I want to get the amount from my foo bank account
//Foo Bank uses a web service that allows cross site access
//No bank would ever do this, but I just want to understand how to with $.getJSON.
var fooDollars = function (id) {
    var value;
    $.getJSON('http://foobank.com/accounts/' + id, null, function (data) {
        value = data.checking;
    });

    //I'm pretty sure this is wrong with an asynchronous call.
    return value;
};

var barDollars = function (id) {
    //have to use jsonp for bar bank
    $.ajax({
        url: 'http://barbank.com/accounts/' + id + '&callback=updateBar',
        dataType: 'jsonp'
    });

    //Not really sure how to return a value from a jsonp ajax call
    return value;
};

function updateBar(data) {
    //Need to take data.savings and get the value back to getAccounts.
    //How? I have no idea. 
}

我有点了解jQuery的延迟方法所做的事情,但我对所有部分如何组合起来有点混淆。特别是:

  1. 在第一部分中,我需要等待两个银行帐户服务完成后才能进入下一步。 jQuery在处理等待多个延迟时,但我无法理解你如何等待多个函数返回值。
  2. 在第1部分,Foo Bank,我正在呼叫$.getJSON。我想获取返回的数据对象并获取data.checking。如何将这些信息反馈到getAccounts()?
  3. 在第1部分,Bar Bank,Simlar为2,除了我如何使用JSONP?
  4. 如果我完全偏离轨道并且应该以不同的方式看待它,那么反馈也会受到赞赏。

2 个答案:

答案 0 :(得分:3)

诀窍是来自fooDollars()barDollars()的回复承诺,而非价值回报(以及来自updateCheckbook()的良好衡量标准)。 $.when().then()中的go()等待两个承诺在触发回调之前完成。

坚持使用当前的函数排列,并将伪(尽可能)转换为实际代码,我得到以下结果:

var go = function () {
    var acctId = 12345;
    $.when.apply(null, getAccounts(acctId)).then(function(a1, a2){
        return updateCheckbook({
            id: acctId,
            fooDollars: a1[0].checking,
            barDollars: a2[0].savings
        });
    }).done(function() {
        alert("Checkbook updated");
    });
}

var getAccounts = function(acctId){
    return [
        fooDollars(acctId),
        barDollars(acctId)
    ];
}

var updateCheckbook(myInfo){
    return $.post('http://mySite.com/checkbook/', myInfo);
}

var fooDollars = function (id) {
    return $.getJSON('http://foobank.com/accounts/' + id);
};

var barDollars = function (id) {
    return $.ajax({
        url: 'http://barbank.com/accounts/' + id,
        dataType: 'jsonp'
    });
};

如果您愿意,可以稍微简化一下getAccounts()并直接从fooDollars()致电barDollars()go()

只有我不太确定是jsonp。可能需要一些工作。

答案 1 :(得分:2)

异步函数不返回值。这是你代码中最大的缺陷。 fooDollars无法返回valuegetAccounts无法返回myInfo(假设getAccounts也执行ajax)。

相反,让函数返回jqXHR对象(也是一个promise对象)。

var fooDollars = function (id) {

    return $.getJSON('http://foobank.com/accounts/' + id);

};

getAccounts做同样的事情(我假设它也做ajax),然后你可以这样做:

$.when(fooDollars('foo'),getAccounts('bar')).done(function(fD,gA){
    console.log(fD[0].checking);
    console.log(gA[0]);
})