使用 $.Deferred、promises 和 $.ajax 构建依赖响应映射

Using $.Deferred, promises, and $.ajax to build a dependency response map

我有一组需要请求的 JS 资源。必须保持顺序,并且响应必须按照我请求的顺序进行。以下请求按顺序进行,但我无法捕获整个请求的 .done() promise 回调。

我从我的对象调用 getScripts 方法:

var depArray = ['file1.js', 'file2.js', 'file3.js'];
getScripts(depArray, global_config.jspath + "/");

这在 $.Deferred() 嵌套的 $.when promise 中迭代数组...

    getScripts : function(arr, path) {
        var depMap = [];
        $.Deferred(
            $.map(arr, function(src) {
                $.when(
                    $.ajax({
                            url: (path || "") + src + ".js",
                            success: function (data) {
                                depMap.push(data);
                                //return data;
                            }
                        }
                    )
                ).then(function() {
                    console.log("request complete...", (path || "") + src + ".js");
                    return true;
                });
            })
        ).done(
            function() { alert('completely done!!!!'); }
        );
    },

警报 ('completely done!!!!') 立即触发,不等待 ajax 调用执行和完成。我需要 return 方法中的 depMap 数组,所以我有一个按顺序从调用中获得的所有响应的映射。

响应将是:

['contents from file1.js', 'contents from file2.js', 'contents from file3.js']

但我从来没有 depMap 可以在最后交出。承诺对我来说仍然有点莫名其妙。感谢任何帮助...

好的,需要进行一些清理。首先,删除 $.Deferred - 不需要它,因为您已经有 $.when 承诺。然后你需要构建承诺数组并将其传递给 $.when.

最后,它可以看起来像这样:

getScripts: function(arr, path) {
    // map each promise to its resource and aggregate
    return $.when.apply(null, arr.map(function(src) {
        return $.ajax({url: (path || "") + src + ".js"});
    })).then(function(){
        return [].map.call(arguments, function(x){ return x[0]; }) // just the data
    });
}

演示: http://plnkr.co/edit/DvBj9PcaTQzskCRIUAHZ?p=preview

$.ajax() 函数 return 是一个 jqXHR 对象,它是一个 Promise。 $.when() 函数说它接受一个或多个 Deferred 对象,但它似乎要求它们只是 Promises,而不是完整的 Deferred 对象。因此,您不需要使用 $.Deferred() 为每个 ajax 请求创建 Deferred 对象。您可以只使用 $.ajax() 编辑的对象 return。您可以使用 $.map() 创建承诺数组,按照 ajax 调用的顺序。

最终,您的 getScripts() 函数不能 return depMap 数组,因为它是异步的。相反,它可以写入 return Promise,如下所示。

getScripts: function(arr, path) {
    return $.when.apply($, $.map(arr, function(src) {
        return $.ajax({ url: (path || '') + src + '.js' });
    })).then(function() {
        return (arr.length > 1)
            ? $.map(arguments, function(a) { return a[0]; })
            : [arguments[0]];
    });
},

有关如何从 $.when(...).then() 函数的参数构造 return 数组到其回调函数的信息,请参阅 this Whosebug answer。 (.done() 的相同信息适用于 .then()。)

Demo on jsfiddle