3

我有一个应用程序,我从多个来源提取数据,并且只有当所有数据都被拉入时,我才想继续。我希望数据尽可能快,所以使用并行请求。

为了弄清楚所有请求何时完成,我这样做:

function getData(cb) {

    var count, data;

    count = 0;
    data = {};

    function getDataDone() {
        count++;
        //only call callback when all async requests are done
        if (count === 3 && cb) {
            cb(data);
        }
    }

    foo.doAsync({
        success: function (d) {
            data.foo = d;
            getDataDone();
        }
    });

    bar.doAsync({
        success: function (d) {
            data.bar = d;
            getDataDone();
        }
    });

    $.getJSON("/api/", function (d) {
        data.user = d;
        getDataDone();
    });

} //end getData


getData(function (data) {

    //application data loaded, do stuff
    data.foo;
    data.bar;
    data.user;

});

foo.doAsyncbar.doAsync并且$.getJSON请求发生是并行的,当完成时,它们会调用getDataDone(),这会增加一个计数器。如果计数器等于预期的请求数,则运行回调。

在这种情况下如何应用 jQuery.deferred ?编码可以正常工作。使用 deferred 比我所拥有的有什么好处吗?

4

2 回答 2

4
var d1 = $.Deferred();
foo.doAsync({
    success: function (d) {
        data.foo = d;
        d1.resolve();
    }
});

var d2 = $.Deferred();
bar.doAsync({
    success: function (d) {
        data.bar = d;
        d2.resolve();
    }
});

var json_deferred = $.getJSON("/api/", function (d) {
    data.user = d;
    getDataDone();
});

$.when(d1, d2, json_deferred).then(function() {
    alert('all requests finished');
});

使用 deferred 比我所拥有的有什么好处吗?

是的,延迟允许对应用程序流程进行更多控制,并且通常(这种情况也不例外)提供更清晰的解决方案。

提示:如果您只需要回调中的异步请求的结果而不需要其他任何东西 - 您可以将结果传递给resolve调用d1.resolve(d);,然后将其作为then()回调的参数获取,而不是使用共享对象作为临时存储。

如果getJSON()您甚至可以省略回调:

var json_deferred = $.getJSON('/api/');
于 2013-04-07T11:22:55.460 回答
1

使用 jQuery.when:http ://api.jquery.com/jQuery.when/你可以等待几个 Promise 完成。

你可以将你的doAsync()方法包装在 Promise 中。

例如

function doAsync (opts) {
    var msg = this.msg;
    var data = { json: JSON.stringify({ msg: msg }) };
    $.ajax("/echo/json/", {
        type: "post",
        data: data
    }).then(opts.success);
}

var foo = { msg: "foo", doAsync: doAsync };
var bar = { msg: "bar", doAsync: doAsync };

function createPromise (doAsyncAble) {
    var dfd = $.Deferred();
    doAsyncAble.doAsync({
        success: function (d) {
            dfd.resolve(d);
        }
    });
    return dfd.promise();
}

function getData(cb) {
    var fooPromise = createPromise(foo);
    var barPromise = createPromise(bar);
    var apiPromise = $.ajax("/echo/json/", {
        type: "post",
        data: { json: JSON.stringify({ data: "api" }) }
    });
    $.when(fooPromise, barPromise, apiPromise).done(function (fooResponse, barResponse, apiResponse) {
        var data = {};
        data.foo = fooResponse;
        data.bar = barResponse;
        data.user = apiResponse[0];
        cb(data);
    });

} //end getData


getData(function (data) {
    console.log(data);
});

产生:

在此处输入图像描述

您还可以从 getData 返回一个承诺,而不是传入回调。

于 2013-04-07T11:36:03.397 回答