你如何使用 jQuery Deferreds 数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4878887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you work with an array of jQuery Deferreds?
提问by Elf Sternberg
I have an application that requires data be loaded in a certain order: the root URL, then the schemas, then finally initialize the application with the schemas and urls for the various data objects. As the user navigates the application, data objects are loaded, validated against the schema, and displayed. As the user CRUDs the data, the schemas provide first-pass validation.
我有一个需要按特定顺序加载数据的应用程序:根 URL,然后是模式,最后用各种数据对象的模式和 url 初始化应用程序。当用户浏览应用程序时,数据对象被加载、根据模式进行验证并显示。当用户 CRUD 数据时,模式提供首次验证。
I'm having a problem with initialization. I use an Ajax call to fetch the root object, $.when(), and then create an array of promises, one for each schema object. That works. I see the fetch in the console.
我在初始化时遇到问题。我使用 Ajax 调用来获取根对象 $.when(),然后创建一个 promise 数组,每个模式对象一个。那个有效。我在控制台中看到了 fetch。
I then see the fetch for all the schemas, so each $.ajax() call works. fetchschemas() does indeed return an array of promises.
然后我看到所有模式的提取,所以每个 $.ajax() 调用都有效。fetchschemas() 确实返回了一个 promise 数组。
However, that final when() clause never fires and the word "DONE" never appears on the console. The source code to jquery-1.5 seems to imply that "null" is acceptable as an object to pass to $.when.apply(), as when() will build an internal Deferred() object to manage the list if no object is passed in.
但是,最后的 when() 子句永远不会触发,并且控制台上永远不会出现“DONE”这个词。jquery-1.5 的源代码似乎暗示“null”作为传递给 $.when.apply() 的对象是可以接受的,因为如果没有对象,when() 将构建一个内部 Deferred() 对象来管理列表通过了。
This worked using Futures.js. How should an array of jQuery Deferreds be managed, if not like this?
这使用 Futures.js 工作。如果不是这样,应该如何管理 jQuery Deferred 数组?
var fetch_schemas, fetch_root;
fetch_schemas = function(schema_urls) {
var fetch_one = function(url) {
return $.ajax({
url: url,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "json"
});
};
return $.map(schema_urls, fetch_one);
};
fetch_root = function() {
return $.ajax({
url: BASE_URL,
data: {},
contentType: "application/json; charset=utf-8",
dataType: "json"
});
};
$.when(fetch_root()).then(function(data) {
var promises = fetch_schemas(data.schema_urls);
$.when.apply(null, promises).then(function(schemas) {
console.log("DONE", this, schemas);
});
});
回答by Raynos
You're looking for
您正在寻找
$.when.apply($, promises).then(function(schemas) {
console.log("DONE", this, schemas);
}, function(e) {
console.log("My ajax failed");
});
This will also work (for some value of work, it won't fix broken ajax):
这也将起作用(对于某些工作价值,它不会修复损坏的 ajax):
$.when.apply($, promises).done(function() { ... }).fail(function() { ... });`
You'll want to pass $
instead of null
so that this
inside $.when
refers to jQuery
. It shouldn't matter to the source but it's better then passing null
.
你会想要传递$
而不是null
让this
inside$.when
指代jQuery
. 这对源来说应该无关紧要,但它比通过更好null
。
Mocked out all your $.ajax by replacing them with $.when
and the sample works
通过替换它们来模拟所有 $.ajax$.when
并且示例有效
So it's either a problem in your ajax request or the array your passing to fetch_schemas.
因此,这要么是您的 ajax 请求中的问题,要么是您传递给 fetch_schemas 的数组的问题。
回答by crispyduck
The workaround above (thanks!) doesn't properly address the problem of getting back the objects provided to the deferred's resolve()
method because jQuery calls the done()
and fail()
callbacks with individual parameters, not an array. That means we have to use the arguments
pseudo-array to get all the resolved/rejected objects returned by the array of deferreds, which is ugly:
上面的解决方法(谢谢!)没有正确解决取回提供给 deferredresolve()
方法的对象的问题,因为 jQuery使用单个参数而不是数组调用done()
和fail()
回调。这意味着我们必须使用arguments
伪数组来获取延迟数组返回的所有已解决/拒绝的对象,这很丑陋:
$.when.apply($, promises).then(function() {
var schemas=arguments; // The array of resolved objects as a pseudo-array
...
};
Since we passed in an array of deferreds, it would be nice to get back an array of results. It would also be nice to get back an actual array instead of a pseudo-array so we can use methods like Array.sort()
.
因为我们传入了一个延迟数组,所以返回一个结果数组会很好。返回一个实际数组而不是伪数组也很好,这样我们就可以使用像Array.sort()
.
Here is a solution inspired by when.js's when.all()
method that addresses these problems:
这里是通过激发溶液when.js的when.all()
方法,该方法解决了这些问题:
// Put somewhere in your scripting environment
if (jQuery.when.all===undefined) {
jQuery.when.all = function(deferreds) {
var deferred = new jQuery.Deferred();
$.when.apply(jQuery, deferreds).then(
function() {
deferred.resolve(Array.prototype.slice.call(arguments));
},
function() {
deferred.fail(Array.prototype.slice.call(arguments));
});
return deferred;
}
}
Now you can simply pass in an array of deferreds/promises and get back an array of resolved/rejected objects in your callback, like so:
现在你可以简单地传入一个延迟/承诺数组并在你的回调中返回一个已解决/拒绝的对象数组,如下所示:
$.when.all(promises).then(function(schemas) {
console.log("DONE", this, schemas); // 'schemas' is now an array
}, function(e) {
console.log("My ajax failed");
});
回答by pashaplus
If you are using ES6 version of javascript There is a spread operator(...) which converts array of objects to comma separated arguments.
如果您使用的是 ES6 版本的 javascript 有一个扩展运算符 (...) 可以将对象数组转换为逗号分隔的参数。
$.when(...promises).then(function() {
var schemas=arguments;
};
More about ES6 spread operator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operatorfind here
有关 ES6 扩展运算符的更多信息https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator在这里找到
回答by CALL ME TZ
extends when with this code:
使用此代码时扩展:
var rawWhen = $.when
$.when = function(promise) {
if ($.isArray(promise)) {
var dfd = new jQuery.Deferred()
rawWhen.apply($, promise).done(function() {
dfd.resolve(Array.prototype.slice.call(arguments))
}).fail(function() {
dfd.reject(Array.prototype.slice.call(arguments))
})
return dfd.promise()
} else {
return rawWhen.apply($, arguments)
}
}