异步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。