這篇文章主要介紹了JavaScript中Promise的使用,特別jQuery的promise使用是當下開發圈中的熱門,需要的朋友可以參考下
摘錄 – Parse JavaScript SDK現在提供了支持大多數異步方法的兼容jquery的Promises模式,那麼這意味著什麼呢,讀完下文你就了解了。
“Promises” 代表著在javascript程序裡下一個偉大的范式,但是理解他們為什麼如此偉大不是件簡單的事。它的核心就是一個promise代表一個任務結果,這個任務有可能完成有可能沒完成。Promise模式唯一需要的一個接口是調用then方法,它可以用來注冊當promise完成或者失敗時調用的回調函數,這在CommonJS Promises/A proposal.大體講到了。比如,我想保存一個Prase.Object對象,這是個異步操作,在舊的回調范式中,你的代碼可能這樣寫:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 object.save({ key: value }, { success:function(object) { // the object was saved. }, error:function(object, error) { // saving the object failed. } }); 在新的Promise范式中,同樣的代碼你可以這樣寫: object.save({ key: value }).then( function(object) { // the object was saved. }, function(error) { // saving the object failed. });沒有多大的區別?那麼有啥大不了的地方呢?好吧,promises的真正強大之處在於多重的鏈接,當調用promise.then(func)時返回一個新的promise,它不會執行直到上一個完成。但是這裡有一種特殊的情況,如果我的回調通過then返回一個新的promise,那麼通過then返回的promise將不會執行,直到回調執行完成。詳細細節請參考 Promises/A+,這是個復雜的規則,通過例子我們能更清楚的認識下.
假設你寫了段登陸的代碼,查找對象然後更新它。在舊的回調范式中,你可以使用金字塔式的代碼完成:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 Parse.User.logIn("user","pass", { success:function(user) { query.find({ success:function(results) { results[0].save({ key: value }, { success:function(result) { // the object was saved. } }); } }); } });這看起來已經很可笑,更可笑的是甚至沒有任何錯誤處理。但是promise鏈式的結構,使代碼看起來更舒服了:
?
1 2 3 4 5 6 7 Parse.User.logIn("user","pass").then(function(user) { returnquery.find(); }).then(function(results) { returnresults[0].save({ key: value }); }).then(function(result) { // the object was saved. });哇!好多啦!
錯誤處理
上面的代碼簡單期間沒有添加錯誤處理,但是添加了後你會發現在舊的回調代碼中一團糟:
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Parse.User.logIn("user","pass", { success:function(user) { query.find({ success:function(results) { results[0].save({ key: value }, { success:function(result) { // the object was saved. }, error:function(result, error) { // An error occurred. } }); }, error:function(error) { // An error occurred. } }); }, error:function(user, error) { // An error occurred. } });由於promises知道處理是否完成,它可以傳遞錯誤,不執行任何回調直到遇到錯誤。比如,上面的代碼可以簡寫為:
?
1 2 3 4 5 6 7 8 9 Parse.User.logIn("user","pass").then(function(user) { returnquery.find(); }).then(function(results) { returnresults[0].save({ key: value }); }).then(function(result) { // the object was saved. },function(error) { // there was some error. });通常,開發者認為一個異步的promise失敗等同於拋出一個異常。事實上,如果一個回調拋出一個錯誤,promise將返回失敗信息。把錯誤傳遞到下一個可用的錯誤處理器等同於拋出一次異常直到捕獲處理。
jQuery, Backbone, 和 Parse
有很多實現了promises的庫供開發者可用。 像jQuery的 Deferred, 微軟的 WinJS.Promise, when.js, q, 和dojo.Deferred.
然而,有個有趣的地方需要了解。 你可以在這裡讀到 long and fascinating jQuery pull request discussion, jQuery的實現沒有完全按照Promises/A的規則來,很多地方用了其他實現方式,實驗時,我發現只有一個地方不太一樣。如果一個錯誤處理器返回一些其他的信息,而不單純返回一個promise,大多數實現會考慮處理這個錯誤,不做錯誤傳遞。然而,jquery不認為在此處處理這個錯誤,而是把它向前傳遞。雖然,來自不同系統的promise應該能無縫的混合使用,但是你還是應當注意些。一個潛在的問題是會在錯誤處理器中返回promises(替換原始數值),因為它們會被同等對待。
?
1 2 3 4 5 6 7 8 9 10 doFailingAsync().then(function() { // doFailingAsync doesn't succeed. },function(error) { // Try to handle the error. return"It's all good."; }).then(function(result) { // Non-jQuery implementations will reach this with result === "It's all good.". },function(error) { // jQuery will reach this with error === "It's all good.". });在 Backbone 0.9.10最新版本中,異步方法現在返回一個 jqXHR,這是jquery promise的一種類型。Parse JavaScript SDK的一個目標是盡可能的和Backbone兼容,我們不能返回一個jqXHR,因為它在 Cloud Code上不能很好地工作,因此,我們不都添加一個 Parse.Promise類,它遵照jQuery Deferred的標准。 Parse JavaScript SDK最新版本已經更新了所有的異步方法來支持這些新的對象,舊的回調方法仍然可用。但是基於上面列出的例子,我相信你更喜歡新的方式。所以試試promises吧!