为什么callback比承诺更“紧密结合”?
你能解释我以下的短语(采取从堆栈溢出问题的答案JavaScript中的延期,承诺和未来之间有什么区别? )?
使用jQuery承诺反对使用以前的jQuerycallback的优点是什么?
不是直接将callback函数传递给函数,而是通过使用promise来导致紧密耦合的接口,从而可以分别关注同步或asynchronous的代码。
我不认为承诺多less会比callback更加耦合,几乎相同。
承诺但是有其他的好处:
-
如果你公开一个callback,你必须logging它是否会被调用一次(如在jQuery.ajax)或不止一次(如在Array.map)。 承诺总是被称为一次。
-
没有办法调用它的callback抛出和exception,所以你必须提供另一个callback的错误情况。
-
只有一个callback可以被注册,不止一个用于承诺,你可以在事件发生后注册它们,你将会被调用。
-
在一个types化的声明(Typescript)中,Promise更容易读取签名。
-
将来,您可以利用asynchronous/收益语法。
-
因为它们是标准的,所以可以制作像这样的可重用组件:
disableScreen<T>(promiseGenerator: () => Promise<T>) : Promise<T> { //create transparent div return promiseGenerator.then(val=> { //remove transparent div return val; }, error=>{ //remove transparent div throw error; }); } disableScreen(()=>$.ajax(....));
更多内容: http : //www.html5rocks.com/en/tutorials/es6/promises/
编辑:
- 另一个好处是编写一个N个asynchronous调用序列,而不需要N个缩进级别。
另外,虽然我仍然认为这不是主要观点,但现在我认为他们有点松散耦合,因为这个原因:
-
它们是标准的(或者至less是try):C#或Java中使用string的代码比C ++中的类似代码更加糟糕,因为string的不同实现使得它更加可重用。 有一个标准的承诺,调用者和执行不太相互耦合,因为他们没有必要就自定义的参数订单,名称等自定义callback(双)的认同…有很多不同的事实对承诺的口味并没有帮助思想。
-
他们促进了更多基于expression式的编程,更容易编写,caching等。
var cache: { [key: string] : Promise<any> }; function getData(key: string): Promise<any> { return cache[key] || (cache[key] = getFromServer(key)); }
你可以认为基于expression式的编程比命令/callback编程更松散耦合,或者至less他们追求的是相同的目标:可组合性。
承诺是一个表示asynchronous操作结果的对象,因此可以将它传递出去,从而为您提供更大的灵活性。
如果使用callback,则在调用asynchronous操作时,必须指定如何处理,从而进行耦合。 随着承诺,你可以指定以后如何处理。
下面是一个例子,假设你想通过ajax加载一些数据,并在做这个时想显示一个加载页面。
通过callback:
void loadData = function(){ showLoadingScreen(); $.ajax("http://someurl.com", { complete: function(data){ hideLoadingScreen(); //do something with the data } }); };
处理返回数据的callback函数必须调用hideLoadingScreen。
有了承诺,您可以重写上面的代码片段,使其变得更具可读性,并且不必将hideLoadingScreen放在完整的callback中。
承诺
var getData = function(){ showLoadingScreen(); return $.ajax("http://someurl.com").promise().always(hideLoadingScreen); }; var loadData = function(){ var gettingData = getData(); gettingData.done(doSomethingWithTheData); } var doSomethingWithTheData = function(data){ //do something with data };
更新:我写了一篇博客文章 ,提供了额外的例子,并提供了什么是一个承诺,以及如何使用callback使用可以比较清楚的描述。
由于操作不需要“知道”它是如何继续的,所以它只需要知道什么时候准备好就可以了。
当你使用callback时,asynchronous操作实际上有一个引用它的延续,这不是它的业务。
借助promise,您甚至可以在决定如何解决问题之前轻松地创build一个asynchronous操作的expression式。
所以承诺有助于将链接事件与实际工作分开。
承诺将对延迟响应的概念进行具体化。 他们使asynchronous计算成为一stream的公民,因为你可以通过它。 它们允许你定义结构,如果你想 – 一元结构,你可以build立更高阶的组合器,大大简化代码。
例如,你可以有一个函数,它需要一个promise数组并返回一个数组的承诺(通常这被称为sequence
)。 callback很难做,甚至不可能。 而这样的组合器不仅使代码更容易编写,而且使其更容易阅读。
现在考虑回答你的问题。 callback是一个特别的解决scheme,承诺允许更清晰的结构和可重用性。
它们不是,这只是一个合理化,那些完全忽略承诺的人使用的理由是编写比使用callback编写的代码更多的代码。 考虑到这样做显然没有任何好处,你至less可以总是告诉自己,代码不太耦合或什么的。
看看有什么承诺,为什么我应该使用它们来获得实际的具体好处。