JQuery Deffered是JQuery庫(kù)中一個(gè)非常強(qiáng)大的工具,它專(zhuān)門(mén)用來(lái)管理異步任務(wù)的狀態(tài)。在異步任務(wù)中,我們可以使用Promise模式來(lái)獲取任務(wù)的狀態(tài)和結(jié)果,而JQuery Deffered則是Promise模式的實(shí)現(xiàn)。
var deferred = $.Deferred(); //異步任務(wù)開(kāi)始,改變deferred對(duì)象的狀態(tài) setTimeout(function(){ deferred.resolve("Task is completed!"); }, 5000); //在任務(wù)完成后執(zhí)行回調(diào)函數(shù) deferred.done(function(msg){ console.log(msg); //Task is completed! });
上面的代碼表示我們創(chuàng)建了一個(gè)deferred對(duì)象,并且在5秒后使用resolve方法改變了該對(duì)象的狀態(tài),表示任務(wù)已經(jīng)完成。最后我們使用done方法添加了一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)會(huì)在任務(wù)完成后被執(zhí)行。
接下來(lái)讓我們來(lái)看一下JQuery Deffered的源碼實(shí)現(xiàn)。
function Deferred(func) { var tuples = [ // action, add listener, listener list, final state [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], [ "notify", "progress", jQuery.Callbacks("memory") ] ], state = "pending", promise = { state: function() { return state; }, always: function() { deferred.done(arguments).fail(arguments); return this; }, then: function( /* fnDone, fnFail, fnProgress */ ) { var fns = arguments; return jQuery.Deferred(function(newDefer) { jQuery.each(tuples, function(i, tuple) { var fn = jQuery.isFunction(fns[i]) && fns[i]; // deferred[ done | fail | progress ] for forwarding actions to newDefer deferred[tuple[1]](function() { var returned = fn && fn.apply(this, arguments); if (returned && jQuery.isFunction(returned.promise)) { returned.promise() .done(newDefer.resolve) .fail(newDefer.reject) .progress(newDefer.notify); } else { newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments); } }); }); fns = null; }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function(obj) { return obj != null ? jQuery.extend( obj, promise ) : promise; } }, deferred = {}; // Add list-specific methods jQuery.each(tuples, function(i, tuple) { var list = tuple[2], stateString = tuple[3]; // promise[ done | fail | progress ] = list.add promise[tuple[1]] = list.add; // Handle state if (stateString) { list.add(function() { // state = [ resolved | rejected ] state = stateString; // [ reject_list | resolve_list ].disable; progress_list.lock }, tuples[i ^ 1][2].disable, tuples[2][2].lock ); } // deferred[ resolve | reject | notify ] deferred[tuple[0]] = function() { deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments); return this; }; deferred[tuple[0] + "With"] = list.fireWith; }); // Make the deferred a promise promise.promise(deferred); // Call given func if any if (func) { func.call(deferred, deferred); } // All done! return deferred; }
上面代碼中我們可以看到Deferred函數(shù),它返回一個(gè)deferred對(duì)象。這個(gè)對(duì)象中包含了許多方法,比如 resolve、reject、notify等。
當(dāng)我們調(diào)用resolve方法時(shí),會(huì)改變deferred對(duì)象的狀態(tài)為resolved,而當(dāng)我們調(diào)用reject方法時(shí),則將狀態(tài)改為rejected。
promise方法返回一個(gè)Promise對(duì)象,這個(gè)對(duì)象可以獲取當(dāng)前異步任務(wù)的狀態(tài)和結(jié)果。我們可以在異步任務(wù)完成后使用這個(gè)對(duì)象的then方法注冊(cè)回調(diào)函數(shù),或者在異步任務(wù)執(zhí)行成功或失敗后使用always方法添加一個(gè)回調(diào)函數(shù)。
總之,通過(guò)閱讀這份源碼,相信你已經(jīng)掌握了JQuery Deffered的實(shí)現(xiàn)原理,可以使用它來(lái)更好地管理你的異步任務(wù)了。