8

I need a method to fetch different scripts with a callback. This method works ok:

fetchScripts:function() {
    var _this=this;
    $.when(
        $.ajax({
            url:_this.url + 'library/script-one.js',
            type:'get',
            cache:true
        }),
        $.ajax({
            url:_this.url + 'library/script-two.js',
            type:'get',
            cache:true
        }),
        { .... },
        $.ajax({
            url:_this.url + 'library/script-n.js',
            type:'get',
            cache:true
        })
    ).then(function() {
        console.log('fetch is done');

    })
},

But i'd like to more generalize the method because redundany is increasing. Is it possible to pass a promise to $.when()? Below my first attempt - but url is always the same, i.e. 'script-n.js' Maybe i missed the point and you could illustrate a more "beauty" solution

fetchScripts:function() {
    this.deferred=new $.Deferred();
    this.promise=this.deferred.promise();
    var _this=this;
    $.each([
        'script-one.js',
        'script-two.js',
        ( .... ),
        'script-n.js'
    ],function() {
        _this.script=this;
        _this.promise.then(function(){
            return $.ajax({
                url:_this.url + 'library/' + _this.script,
                type:'get',
                cache:true
            })
        });
    });
    $.when(
        this.promise
    ).then(function() {
        console.log('fetch is done');

    });
    this.deferred.resolve();
},

2 Answers 2

28

You still need $.when. But instead, create an array of Deferreds (or promises) and then apply it to $.when:

fetchScripts:function() {
    var base = this.url;
    var defaults = {
        type:'get',
        cache:true
    };

    var libraries = [
        'library/script-one.js',
        'library/script-two.js',
        'library/script-n.js'
    ];

    var deferreds = $.map(libraries, function(current) {
        var ajaxOptions = $.extend({ url:  base + current }, defaults);
        return $.ajax(ajaxOptions);
    });

    $.when.apply($, deferreds).then(function() {
        console.log('All done');
    });
}

Alternatively to extending the default settings, you could just use $.ajax(defaults).

Sign up to request clarification or add additional context in comments.

2 Comments

To access the results of the deferred values you can use the arguments magic variable inside the anonymous function passed to .then;
I've noticed that when using then(), if any of the request fails, you will enter its function despite not being all done, whereas with done(), it will only be executed when the last one to remain is finished, no matter if some fail.
4

Try

fetchScripts: function() {
    var deferred = new $.Deferred();
    var _this=this;

    var promises = $.map([
        'script-one.js',
        'script-two.js',
        ( .... ),
        'script-n.js'
    ], function(item, idx) {
        return $.ajax({
            url:_this.url + 'library/' + item.script,
            type:'get',
            cache:true
        })
    });

    $.when.apply($, promises).then(function() {
        console.log('fetch is done');
        deferred.resolve()
    });
    return deferred.promise();
}

2 Comments

I think you mean $.map, not $.each. Also just item, not item.script :-)
@RocketHazmat yes, copy paste mistake

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.