2013-01-02 112 views
50

可能重複:
What are the differences between Deferred, Promise and Future in Javascript?異步JavaScript - 回調VS遞延/無極

最近我一直在做,以提高我的JavaScript應用程序質量的努力。我已經採用的一種模式是使用單獨的「數據上下文」對象爲我的應用程序加載數據(以前我直接在我的視圖模型中執行此操作)。

下面的示例返回客戶端上初始化的數據:

var mockData = (function($, undefined) { 

    var fruit = [ 
     "apple", 
     "orange", 
     "banana", 
     "pear" 
     ]; 

    var getFruit = function() { 
     return fruit; 
    }; 

    return { 
     getFruit: getFruit 
    } 
})(jQuery); 

在大多數情況下,我們會從服務器加載數據,所以我們不能回到立即響應。看來我對我們如何處理這個我們的API在兩個選項:

  1. 使用回調
  2. 返回一個promise

以前我一直用的回調方法:

var getFruit = function(onFruitReady) { 
    onFruitReady(fruit); 
}; 

// ... 

var FruitModel = function(dataContext, $) { 
    return { 
     render: function() { 
      dataContext.getFruit(function(fruit) { 
       // do something with fruit 
      }); 
     } 
    }; 
}; 

不過,我可以看到它是如何可能的回調地獄結束,構建複雜的JavaScript應用程序時尤其如此。

然後我遇到了Promises設計模式。相反,需要調用者提供一個回調,我不是返回一個「承諾」可以觀察到的:

var getFruit = function() { 
    return $.Deferred().resolve(fruit).promise(); 
}; 

// ... 
dataContext.getFruit().then(function(fruit) { 
    // do something with fruit 
}); 

我可以看到使用這種模式的明顯的好處,尤其是因爲我可以在多個延遲對象可能wait在爲單個頁面應用程序加載初始化數據時非常有用。

但是,在開始使用憤怒之前,我很想了解每種模式的優缺點。我也對這是否是其他圖書館正在發展的方向感興趣。jQuery似乎就是這種情況。

這是我用來測試的小提琴的link

+4

那麼好消息:jQuery的AJAX API的*已經*回報承諾! – Pointy

+0

[請閱讀此處的機制。](http://api.jquery.com/jQuery.ajax/#jqXHR) – Pointy

+0

是的,這是我在第一個地方遇到的模式,因爲我正在尋找一種方法抽象我的ajax調用。 –

回答

18

承諾也依賴於現場背後的回調,所以它不是真正的一對一。

回調的好處是它們很容易用普通的JavaScript實現(例如在ajax調用中)。

Promise需要一個額外的抽象層,這通常意味着您將依賴一個庫(因爲您已經在使用jQuery而不是您的問題)。當你並行處理多個異步調用時,它們是完美的。

+9

請注意,截至2014年3月,瀏覽器已開始實施本地承諾,所以我的陳述僅適用於polyfills。 – Christophe

3

從讀取@Pointy鏈接的jQuery docs來,它聽起來就像不同的是,延遲API允許你指定一個以上的功能,當您的請求完成被稱爲:

在jQuery 1.5 ,錯誤(失敗),成功(完成)和完成(總是,從jQuery 1.6開始)回調鉤子是先入先出的受管隊列。這意味着您可以爲每個掛鉤分配多個回叫。請參閱Deferred對象方法,它們在內部爲這些$ .ajax()回調鉤子實現。

參見:deferred.then()

+1

這不是說延遲/承諾*允許*指定多個被調用的函數,只要他們這樣做*更容易*。 (a)可以在代碼中的任何位置添加函數(例如'.done()'或'.fail()'),僅受限於範圍內的Deferred/promise,以及(b)函數在Deferred已解決/拒絕後添加將立即觸發。通過公開其內部的'.Callbacks()'實用程序,jQuery使這種類型的功能成爲可能*而不使用Deferreds/promise,但是它們使編碼/調試不再煩惱。 –