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

异步JavaScript-回调与延迟/承诺,javascript,jquery-deferred,commonjs,Javascript,Jquery Deferred,Commonjs,可能重复: 最近,我一直在努力提高JavaScript应用程序的质量 我采用的一种模式是使用单独的“数据上下文”对象为我的应用程序加载数据(以前我直接在视图模型中这样做) 以下示例返回在客户端上初始化的数据: var mockData = (function($, undefined) { var fruit = [ "apple", "orange", "banana", "pear" ];

可能重复:

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

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

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

var mockData = (function($, undefined) {

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

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

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

  • 使用回调
  • 返回一个
  • 以前我一直使用回调方法:

    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
    });
    
    我可以看到使用此模式的明显好处,特别是因为我可以对多个延迟对象进行
    等待
    ,这在为单页应用程序加载初始化数据时非常有用

    然而,在我开始在愤怒中使用这两种模式之前,我渴望了解每种模式的利弊。我还对其他图书馆是否朝着这个方向发展感兴趣。jQuery似乎就是这样


    下面是我用于测试的一个例子。

    承诺也依赖于幕后的回调,所以这不是一对另一

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

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

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

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


    另请参见:

    好消息:jQueryAjax API已经兑现了承诺!是的,这就是我在寻找一种抽象ajax调用的方法时第一次遇到这种模式的原因。我认为回调要快一点,但我真的很喜欢你的问题,并且对答案感兴趣!啊。我的意思是,你真的不需要增加太多;这些调用的返回值已经可以使用了,因此这只是一个简单的问题,即摆脱传递“成功”回调的习惯,养成调用
    .done()
    等的习惯。延迟/承诺并不是允许您指定要调用的多个函数,而是让调用变得更容易。特别的特点是:(a)可以在代码中的任何地方添加函数(例如,
    .done()
    .fail()
    ),只要延迟/承诺在范围内,并且(b)延迟解决/拒绝后添加的函数将立即启动。通过公开其内部
    .Callbacks()
    实用程序,jQuery使这种类型的功能成为可能,而无需使用延迟/承诺,但它们减轻了编码/调试的痛苦。请注意,截至2014年3月,浏览器已开始实现本机承诺,因此我的声明仅适用于polyfills。