51

可能重复:
Javascript 中的 Deferred、Promise 和 Future 有什么区别?

最近我一直在努力提高我的 JavaScript 应用程序的质量。

我采用的一种模式是使用单独的“数据上下文”对象为我的应用程序加载数据(以前我直接在我的视图模型中执行此操作)。

以下示例返回在客户端初始化的数据:

var mockData = (function($, undefined) {

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

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

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

在大多数情况下,我们将从服务器加载数据,因此我们无法立即返回响应。对于我们如何在 API 中处理这个问题,我似乎有两种选择:

  1. 使用回调
  2. 回报承诺

以前我总是使用回调方法:

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 似乎就是这种情况。

这是我用于测试的小提琴的链接。

4

2 回答 2

18

Promise 也依赖于幕后的回调,所以它并不是真正的一对一。

回调的好处是它们很容易用纯 JavaScript 实现(例如在 ajax 调用中)。

Promise 需要一个额外的抽象层,这通常意味着您将依赖一个库(在您的情况下这不是问题,因为您已经在使用 jQuery)。当您并行处理多个异步调用时,它们是完美的。

于 2013-01-02T19:26:37.957 回答
3

从阅读 @Pointy 链接到的jQuery 文档,听起来不同之处在于 Deferred API 允许您指定在请求完成时要调用的多个函数:

从 jQuery 1.5 开始,错误(失败)、成功(完成)和完成(始终,从 jQuery 1.6 开始)回调挂钩是先进先出的托管队列。这意味着您可以为每个挂钩分配多个回调。请参阅延迟对象方法,这些方法是在内部为这些 $.ajax() 回调挂钩实现的。

参见:deferred.then()

于 2013-01-02T19:35:01.573 回答