【问题标题】:jQuery deferred with non jQuery ajaxjQuery 延迟与非 jQuery ajax
【发布时间】:2013-03-29 12:00:00
【问题描述】:

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

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

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 有什么好处吗?

【问题讨论】:

    标签: jquery ajax jquery-deferred promise


    【解决方案1】:
    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/');
    

    【讨论】:

    • 我只需要 Hint: 中的部分。太好了!
    【解决方案2】:

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

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

    For example:

    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 返回一个承诺,而不是传入回调。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 2011-09-11
      • 2013-12-25
      • 2016-12-01
      • 2014-03-15
      • 2015-06-07
      相关资源
      最近更新 更多