$.fn
- eachDeferred
.$.Deferred
jQuery objects. (function ($) { $.fn.extend({ /* * Iterates over jQuery object collection using deferred callbacks. * the function assigned for iterator should return promise. * resolved promises notify the main deferred, so we can track each loop result. * returns promise. */ eachDeferred: function (c) { var that = this, dfd = $.Deferred(), elms = $.makeArray(that), i = elms.length, next = function () { setTimeout(function () { elms.length ? cb(elms.shift()) : dfd.resolve(that); }, 0); }, cb = function (elm) { $.when(c.call(elm, i - elms.length, $(elm))).done(function (result) { dfd.notify(result); next(); }); }; next(); return dfd.promise(); } }); })(jQuery);
$.Deferred
object to determine when the current iteration is finished. The plug-in code itself eachDeferred
also returns a $.Deferred
object that can be used in the call chain. The object notifies about the results of each iteration through notify/progress
, passing the result of the iteration ( arg
, which can be returned from $.Deferred.resolve(arg)
of the loop handler function) to the code of the .progress(function(arg){})
handler .progress(function(arg){})
( if available). that.widgets.eachDeferred(function (i, widget) { return that.renderContent(widget); }).done(dfd.resolve);
renderContent
asynchronously pulls data from the server and displays the contents of the widget. Visually, it feels like each widget is loading in turn. In the case of using the usual $.Deferred
( $.get().success()
) mechanism, the widgets would be displayed randomly - which would rather load. var dfd = $.Deferred(), _r = []; xml.children("Tree").eachDeferred(function (i, xmlNode) { return that._buildTreeContents(xmlNode); }).progress(function (treeContents) { _r.push(treeContents); }).done(function () { dfd.resolve(_r); }); return dfd.promise();
_buildTreeContents
asynchronously builds the tree _buildTreeContents
, passing us the result of each iteration (we save it into an array). At the end of the collection processing, we have a common tree markup, which we can insert into the page.next()
. The timeout is needed because of the jQuery code - the .notify()
call in it occurs after the same timeout. This is done so that the browser can complete the processing of the current Javascript VM stack..notify()
- we also need to notify the end of the iteration first, and then proceed to the next one.Source: https://habr.com/ru/post/143592/
All Articles