异步 JavaScript - 回调与延迟/承诺

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14127703/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 15:47:31  来源:igfitidea点击:

Asynchronous JavaScript - Callbacks vs Deferred/Promise

javascriptjquery-deferredcommonjs

提问by Ben Foster

Possible Duplicate:
What are the differences between Deferred, Promise and Future in Javascript?

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

Lately I've been making an effort to improve the quality of my JavaScript applications.

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

One pattern I've adopted is to use a separate "data context" object to load data for my application (previously I was doing this directly in my view models).

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

The following example returns data that is initialized on the client:

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

var mockData = (function($, undefined) {

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

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

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

In most cases we'll be loading data from the server so we can't return an immediate response. It seems I have two options for how we handle this in our API:

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

  1. Using a callback
  2. Returning a promise.
  1. 使用回调
  2. 返回一个承诺

Previously I'd always used the callback approach:

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

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

// ...

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

However, I can see how it's possible to end up in callback hell, especially when building complex JavaScript applications.

但是,我可以看到如何最终陷入回调地狱,尤其是在构建复杂的 JavaScript 应用程序时。

Then I came across the Promises design pattern. Instead of requiring the caller to supply a callback, I instead return a "promise" that can be observed:

然后我遇到了 Promises 设计模式。我没有要求调用者提供回调,而是返回一个可以观察到的“承诺”:

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

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

I can see obvious benefits of using this pattern, especially since I can waiton multiple deferred objects which could be very useful when loading initialization data for a single page application.

我可以看到使用这种模式的明显好处,特别是因为我可以wait处理多个延迟对象,这在为单页应用程序加载初始化数据时非常有用。

However, I'm keen to understand the pros and cons of each pattern before I start to use either in anger. I'm also interested in whether this is the direction other libraries are going in. It seems to be the case with jQuery.

然而,在我开始在愤怒中使用任何一种模式之前,我很想了解每种模式的利弊。我也对这是否是其他库的发展方向感兴趣。jQuery 似乎就是这种情况。

Here's a linkto the fiddle I'm using for testing.

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

回答by Christophe

Promises also rely on callbacks behind the scene, so it's not really one vs. the other.

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

The benefit of callbacks is that they are easy to implement with plain JavaScript (for example in ajax calls).

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

Promises require an additional abstraction layer, which usually means that you'll rely on a library (not an issue in your case as you are already using jQuery). They are perfect when you deal with multiple async calls in parallel.

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

回答by Max Fellows

From reading the jQuery docsthat @Pointy linked to, it sounds like the difference is that the Deferred API allows you to specify more than one function to be called when your request completes:

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

As of jQuery 1.5, the error (fail), success (done), and complete (always, as of jQuery 1.6) callback hooks are first-in, first-out managed queues. This means you can assign more than one callback for each hook. See Deferred object methods, which are implemented internally for these $.ajax() callback hooks.

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

See also: deferred.then()

另见:deferred.then()