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.
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.
I then see the fetch for all the schemas, so each $.ajax() call works. fetchschemas() does indeed return an array of promises.
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.
This worked using Futures.js. How should an array of jQuery Deferreds be managed, if not like this?
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);
});
});
You're looking for
This will also work (for some value of work, it won't fix broken ajax):
You'll want to pass
$
instead ofnull
so thatthis
inside$.when
refers tojQuery
. It shouldn't matter to the source but it's better then passingnull
.Mocked out all your $.ajax by replacing them with
$.when
and the sample worksSo it's either a problem in your ajax request or the array your passing to fetch_schemas.
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 thedone()
andfail()
callbacks with individual parameters, not an array. That means we have to use thearguments
pseudo-array to get all the resolved/rejected objects returned by the array of deferreds, which is ugly: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()
.Here is a solution inspired by when.js's
when.all()
method that addresses these problems: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:
extends when with this code:
If you are using ES6 version of javascript There is a spread operator(...) which converts array of objects to comma separated arguments.
More about ES6 spread operator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator find here