摘錄 – Parse JavaScript SDK現在提供了支援大多數非同步方法的相容jquery的Promises模式,那麼這代表什麼呢,讀完下文你就了解了。
「Promises」 代表著在javascript程式裡下一個偉大的範式,但是理解他們為什麼如此偉大不是件簡單的事。它的核心就是一個promise代表一個任務結果,這個任務有可能完成有可能沒完成。 Promise模式唯一需要的一個介面是呼叫then方法,它可以用來註冊promise完成或失敗時呼叫的回呼函數,這在CommonJS Promises/A proposal.大體講到了。例如,我想保存一個Prase.Object對象,這是一個非同步操作,在舊的回呼範式中,你的程式碼可能會這樣寫:
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 ,這是個複雜的規則,透過例子我們能更清楚的認識下.
假設你寫了段登陸的程式碼,尋找物件然後更新它。在舊的回呼範式中,你可以使用金字塔式的程式碼完成:
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鍊式的結構,讓程式碼看起來更舒服了:
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. });
哇!好多啦!
錯誤處理
上面的程式碼簡單期間沒有添加錯誤處理,但是添加了後你會發現在舊的回調程式碼中一團糟:
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知道處理是否完成,它可以傳遞錯誤,不執行任何回調直到遇到錯誤。例如,上面的程式碼可以簡寫為:
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(取代原始數值),因為它們會被同等對待。
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吧!