Promises是一個異步編程模型,它經過一組API來規範化異步操做。node
Promises模型的基本概念能夠總結爲:jquery
對於Promises模型而言,已經提出了多個實現的草案:如Promises/A,Promises/B等等。還有一些能夠參看:http://wiki.commonjs.org/wiki/Promisesgit
簡稱「thenable",事實上,每個Promise對象都有一個方法:then(fulfilledHandler,errorHandler,progressHandler)。由於Promise對象有三個狀態:unfulfilled,fulfilled,failed,也就是未完成的,完成的和失敗的。當一個Promise對象由unfulfilled狀態變爲fulfilled狀態後,fulfilledHandler函數會被調用。當進度事件發生時,progressHandler會被調用。一般progress事件能夠省略。github
Deferred概念從jQuery的1.5版本開始引用,它是Promises/A標準的一種衍生實現。經過調用jQuery.Deferred()方法,能夠建立Deferred對象,它是一個能夠鏈式操做的對象,並可以註冊多個回調函數到回調隊列,在異步操做成功或者失敗時轉達消息。編程
defer在英文中的意思是延遲,所以咱們能夠理解爲Deferred對象爲延遲執行的對象。api
Deferred對象有三個動做:resolve(解決)、reject(拒絕)和notify(通知)。數組
Deferred對象能夠經過一些方法主動調用這三個動做:deferred.resolve()、deferred.reject()和deferred.notify()。固然,還有一些回調對應不一樣的狀態,如:promise
有人可能會問then()和always()有什麼區別?其實這兩個是類似的,只是then函數有兩個參數:resolved時的回調和rejected時的回調,至關於將done()和fail()函數合併了,而always函數只有一個回調函數做爲參數,無論是resolved仍是rejected時,都會執行這個回調。app
1 jQuery.Deferred = function( func ) { 2 /* Callback參數 3 once: 全部回調函數只執行一次 4 memory: 觸發回調後對象能夠繼續添加函數,添加的函數會立刻被觸發 5 unique: 保證相同的回調函數只能添加一次 6 stopOnFalse: 當回調返回false時中止觸發 7 */ 8 var tuples = [ 9 // action, add listener, listener list, final state 10 [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], 11 [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], 12 [ "notify", "progress", jQuery.Callbacks("memory") ] 13 ], 14 state = "pending", 15 promise = { 16 state: function() { 17 return state; 18 }, 19 always: function() { 20 deferred.done( arguments ).fail( arguments ); 21 return this; 22 }, 23 then: function( /* fnDone, fnFail, fnProgress */ ) { 24 var fns = arguments; 25 return jQuery.Deferred(function( newDefer ) { 26 jQuery.each( tuples, function( i, tuple ) { 27 var action = tuple[ 0 ], 28 fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; 29 // deferred[ done | fail | progress ] for forwarding actions to newDefer 30 deferred[ tuple[1] ](function() { 31 var returned = fn && fn.apply( this, arguments ); 32 if ( returned && jQuery.isFunction( returned.promise ) ) { 33 returned.promise() 34 .done( newDefer.resolve ) 35 .fail( newDefer.reject ) 36 .progress( newDefer.notify ); 37 } else { 38 newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); 39 } 40 }); 41 }); 42 fns = null; 43 }).promise(); 44 }, 45 // Get a promise for this deferred 46 // If obj is provided, the promise aspect is added to the object 47 promise: function( obj ) { 48 return obj != null ? jQuery.extend( obj, promise ) : promise; 49 } 50 }, 51 deferred = {}; 52 53 // Keep pipe for back-compat 54 promise.pipe = promise.then; 55 56 // Add list-specific methods 57 jQuery.each( tuples, function( i, tuple ) { 58 var list = tuple[ 2 ], 59 stateString = tuple[ 3 ]; 60 61 // promise[ done | fail | progress ] = list.add 62 promise[ tuple[1] ] = list.add; 63 64 // Handle state 65 if ( stateString ) { 66 list.add(function() { 67 // state = [ resolved | rejected ] 68 state = stateString; 69 70 // [ reject_list | resolve_list ].disable; progress_list.lock 71 }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); 72 } 73 74 // deferred[ resolve | reject | notify ] 75 deferred[ tuple[0] ] = function() { 76 deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); 77 return this; 78 }; 79 deferred[ tuple[0] + "With" ] = list.fireWith; 80 }); 81 82 // Make the deferred a promise 83 promise.promise( deferred ); 84 85 // Call given func if any 86 if ( func ) { 87 func.call( deferred, deferred ); 88 } 89 90 // All done! 91 return deferred; 92 }
此外,還有兩個方法:異步
關於Deferred對象的更多細節請看API: http://api.jquery.com/category/deferred-object/
咱們知道,node.js是異步編程的,對於新手而言,異步編程致使的一個常見的問題就是異步嵌套過深。解決的方法有若干個,一個是使用Event,也就是在合適的時間emit某一個事件,那麼代碼就變爲了一行一行的on('xxx',callback);另外一個解決方法就是使用異步管理的庫,如async等;還有就是咱們如今討論的Promises模型。
Nodejs中比較流行的Promises庫就是Q Library。它的項目主頁是:https://github.com/kriskowal/q
一個例子是:
function get_all_the_things(things) { var the_promises = []; things.forEach(function(thing) { var deferred = Q.defer(); get_a_thing(thing, function(result) { deferred.resolve(result); }); the_promises.push(deferred.promise); }); return Q.all(the_promises); }
還有其餘的功能,因爲還不熟悉,就先到這裏。