JSFiddle - React, Tailwind, and code Playground

HTML

<b>Expected Result</b><br />
a2 fail<br />
a2 always<br />
a3 done<br />
a3 always<br />
a1 done<br />
a1 always<br />
defer always<br />
----------<br /><br />
<b>Actual Result</b><br />

JavaScript

var custom_when = function() {
    var args = Array.prototype.slice.call(arguments, 0);
    console.log(args);
    var callback = args.pop();
    var all = [];
    $.each(args, function(index, def) {
        def.always(function() {
            var idx = all.indexOf(def);
            if (idx !== -1) {
                all.splice(idx, 1);
            }
            if (!all.length) {
                callback();
            }
        });
        all.push(def);
    });
};

var a1 = $.Deferred();
var a2 = $.Deferred();
var a3 = $.Deferred();

a1.done(function() {
    $('body').append('a1 done<br />');     
}).fail(function() {
    $('body').append('a1 fail<br />');     
}).always(function() {
    $('body').append('a1 always<br />');     
});

a2.done(function() {
    $('body').append('a2 done<br />');     
}).fail(function() {
    $('body').append('a2 fail<br />');     
}).always(function() {
    $('body').append('a2 always<br />');     
});

a3.done(function() {
    $('body').append('a3 done<br />');     
}).fail(function() {
    $('body').append('a3 fail<br />');     
}).always(function() {
    $('body').append('a3 always<br />');     
});


custom_when(a1, a2, a3, function() {   
    $('body').append('defer always <-- should be after all<br />'); 
});

setTimeout(function() {
    a1.resolve();
}, 5000);
setTimeout(function() {
    a2.reject();
}, 1000);
setTimeout(function() {
    a3.resolve();
}, 3000);