How do you work with an array of jQuery Deferreds?

前端 未结 4 1089
余生分开走
余生分开走 2020-11-22 15:02

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

相关标签:
4条回答
  • 2020-11-22 15:28

    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:

    $.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().

    Here is a solution inspired by when.js's when.all() method that addresses these problems:

    // 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");
    });
    
    0 讨论(0)
  • 2020-11-22 15:35

    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):

    $.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.

    Mocked out all your $.ajax by replacing them with $.when and the sample works

    So it's either a problem in your ajax request or the array your passing to fetch_schemas.

    0 讨论(0)
  • 2020-11-22 15:46

    If you are using ES6 version of javascript There is a spread operator(...) which converts array of objects to comma separated arguments.

    $.when(...promises).then(function() {
     var schemas=arguments; 
    };
    

    More about ES6 spread operator https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator find here

    0 讨论(0)
  • 2020-11-22 15:47

    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)
        }
    }
    
    0 讨论(0)
提交回复
热议问题