jQuery.Deferred with setTimeout

2k views Asked by At

I created a simple list to test out jQuery Deferred with setTimeout.

<ul>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>

On my script, I created a simple function. The idea behind is that for every LI, it will replace the content at certain interval and when everything is completed, it will print 'all done' message.

function listing() {
    var deferred = $.Deferred();
    var promises = [];
    var promise;
    var index = 0;
    var list = $('ul').find('li');
    list.each(function(index) {
        var that = $(this);
        promise = $.Deferred();
        (function(i){
            setTimeout(function() {
                that.html(i);
                promise.resolve();
                promises.push(promise);
            }, 8000*index);
        })(index);

    });

    $.when.apply(null, promises).then(function() {
        setTimeout(function() {
            deferred.resolve();
        }, 2000);
    });

    return deferred.promise();
}

$.when(listing().done(function() {
    console.log('all done');
}));

Intended result is to have the content of the LI to be replaced every 8 seconds and once it's all replace, it will wait for 2 seconds before it prints 'all done'.

Currently, it will print 'all done' after 2 seconds and will replace LIs after 8 seconds.

I am new with jQuery Deferred, any advice is welcome.

1

There are 1 answers

2
Arun P Johny On BEST ANSWER

The problem is you are not pushing anything to the promises array in the each loop

function listing() {
    var deferred = $.Deferred();
    var promises = [];
    var promise;
    var index = 0;
    var list = $('ul').find('li');
    list.each(function (index) {
        var that = $(this);
        var deferred = $.Deferred();
        setTimeout(function () {
            that.html(index);
            deferred.resolve();
        }, 8000);
        //push the deferred outside the timeout
        promises.push(deferred.promise());
    });

    $.when.apply($, promises).then(function () {
        setTimeout(function () {
            deferred.resolve();
        }, 2000);
    });

    return deferred.promise();
}

$.when(listing().done(function () {
    console.log('all done');
}));

Demo: Fiddle