一般來講,js請求數據,不管是異步仍是同步,都不會當即獲取到結果,一般而言,咱們通常是是使用回調函數再執行,而 deferred就是解決jQuery的回調函數方案,總的來講,deferred對象就是爲了將某個回調函數延遲到某個時機再執行.html
ajax鏈式寫法:jquery
//通常寫法: $.ajax({ url: '', success: function(){}, error: function(){}, }) //deferred $.ajax(url) .done(function(){}) //至關於success .fail(function(){})
指定同一操做的多個函數,容許添加多個函數
寫法也很簡單,直接添加在後面就能夠了。ajax
$.ajax(url) .done(function(){}) .fail(function(){}) .done(function(){})
爲多個函數添加指定回調,能夠爲多個不一樣的函數添加同一個回調事件數組
$.when($.ajax(url),$.ajax(url2)) .done() .fail()爲兩個函數執行操做,若是都成功了就執行done中的回調,若是有一個失敗或所有都失敗,就執行fail中的回調
普通操做的回調
deferred容許任何操做均可以使用deferred對象的方法,指定回調函數promise
var wait = function(de){ var test = function(){ console.log('開始'); de.resolve(); } setTimeout(test, 3000); return de; } $.when(wait($.Deferred())) .done(function(){ console.log('已完成') }) .fail(function(){ console.log('失敗') })
注意: $.when()的參數只能是deferred對象。異步
關於resolve && rejected
在上面的時候,會注意到一個resolve,而且會以爲這種鏈式寫法很眼熟,且對promise有一個簡單瞭解的話,大概就知道了。函數
promise: 一樣也是用於處理異步函數,將異步操做隊列化處理 簡單的promise new promise (function(resolve,rejected){ resolve('成功') }) .then(function(){}) promise.then 接受兩個參數: 1、 resolve 表明成功時調用的函數 2、 rejected 表明失敗時調用的回調 promise的三個狀態值: pending(初始狀態值), fulfilled(操做成功),rejected(操做失敗)$.deferred 一樣也是有三個不一樣的狀態:未完成,已完成,已失敗,當狀態處於已完成(resolve)下回自動調用done()中的回調函數,而resolve()就是人爲將狀態值修改成已完成,同理可證rejected();
API
* $.Deferred()
* $.when()
* deferred.progress()
* deferred.promise()
* deferred.done()
* deferred.fail()學習
來看下jQ的源碼是怎麼處理的:this
Deferred: function(func) { var tuples = [ // action, add listener, callbacks, // ... .then handlers, argument index, [final state] ["notify", "progress", jQuery.Callbacks("memory"), jQuery.Callbacks("memory"), 2 ], ["resolve", "done", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), 0, "resolved" ], ["reject", "fail", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), 1, "rejected" ] ], state = 'pending', // 延遲對象 deferred = {}, promise = { state: function() { return state }, then: function(){}, promise: function(obj) { return obj != null ? jQuery.extend(obj, promise): promise; } } ... }
從代碼來看,定一個了數組tuples,以及初始狀態值。tuples存儲了三個狀態下的所需參數,來看下存儲了寫什麼內容:
[狀態, 對應的處理函數, 利用callbacks建立的回調隊列, then方法的回調隊列, index, 最終的狀態值],
咱們能夠看到最終的狀態值只有reject 和resolve纔有。
ok,已經知道deferred的本質是根據不一樣的狀態調用不一樣的方法,而且使用callbacks添加函數,那麼把tuples遍歷一下,生成隊列;
源碼:url
tuples.forEach(function(tuple){ var list = tuple[2], // 獲取到jQuery.callbacks返回,建立一個隊列 stateString = tuple[5], //獲取到最終狀態描述 //promise[ progress | done | fail ] = list.add promise[tuple[1]] = list.add; // 若是最終狀態值存在,即處於 reject|| resolve 狀態下; if (stateString) { list.add( function() { state = stateString; } .... ) } // 延遲對象狀態 deferred.resolve() //deferred[ 'resolve' | reject | notify] = function(){} deferred[tuple[0]] = function() { deferred[tuple[0]+"Width"](this === deferred ? promise : this, arguments); return this; } //jQuery.callbacks.fireWith //執行隊列,調用處理函數,綁定執行時的上下文 deferred[tuple[0] + "With"] = list.fireWith; }) promise.promise(deferred); return deferred;
已經遍歷生成了3個隊列,並將三個狀態方法掛載在了延遲對象上。
從代碼中能夠看出,在調用deferred[ reject | resolve]時,實際上是調用了deferred[ rejectWith | resolveWith]方法,本質上是對callbacks.fireWith的調用,以用來執行添加的回調函數,同時設置函數的上下文。
而且能夠看的到,deferred[proress | done | fail] 實際上是copy了callbacks.add方法,將回調函數添加在了執行隊列中。
另外關於對jQuery.deferred對象的詳解,使用,http://www.javashuo.com/article/p-bykzzqzg-ee.html 這篇博文轉載了阮大神的,能夠瞅瞅