I have some idea about Deferreds and what they do but I can't understand their usage in a piece of code I am working with right now. This code is from jquery-file-upload plugin and file jquery-fileupload-ui.js:
stop: function (e) {
var that = $(this).data('blueimp-fileupload') ||
$(this).data('fileupload'),
deferred = that._addFinishedDeferreds();
$.when.apply($, that._getFinishedDeferreds())
.done(function () {
that._trigger('stopped', e);
});
that._transition($(this).find('.fileupload-progress')).done(
function () {
$(this).find('.progress')
.attr('aria-valuenow', '0')
.children().first().css('width', '0%');
$(this).find('.progress-extended').html(' ');
deferred.resolve();
}
);
},
_addFinishedDeferreds: function (deferred) {
if (!deferred) {
deferred = $.Deferred();
}
this._finishedUploads.push(deferred);
return deferred;
},
_getFinishedDeferreds: function () {
return this._finishedUploads;
},
In the stop method, there are two constructs that I don't understand:
1)
$.when.apply($, that._getFinishedDeferreds())
.done(function () {
that._trigger('stopped', e);
});
2)
deferred = that._addFinishedDeferreds();
//and later in the _transition function
deferred.resolve();
The second construct repeats throughout the whole code. I can see that _addFinishedDeferreds creates a deferred (if it is not passed as an argument), adds it to _finishedUploads and that deferred is later resolved. But I am missing the meaning of all this. What is it good for? Why the code can't work without it? And I don't understand the meaning of the first construct at all. Anyone can shed some light on this?
First I assume you understand basic usage of Deferreds
, including resolve()
and $.when()
.
From my understand of this code snippet, the stop
function will be called multiple times, each time a new Deferred
is created and will not be resolved until the transition is completed, though I don't know what transition it is because you did not show us its code. The Deferred
object here, is to signal the completion of transition, and then a stopped
event is triggered.
1)
$.when.apply($, that._getFinishedDeferreds())
.done(function () {
that._trigger('stopped', e);
});
$.when.apply($, that._getFinishedDeferreds())
generates a new Deferred
which is resolved after every Deferred
is resolved in the array returned by _getFinishedDeferreds()
. Then the callback function in done()
triggers the stopped
event.
2)
deferred = that._addFinishedDeferreds();
//and later in the _transition function
deferred.resolve();
Your understanding is correct. The intention of this code (if I guess correctly) is to make sure the event is not triggered until all transition is finished.
However if so there's a bug that the event trigger callback:
function () {
that._trigger('stopped', e);
}
is attached each time stop()
is called so the event may be triggered multiple times.