为什么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可以总是告诉自己,代码不太耦合或什么的。

看看有什么承诺,为什么我应该使用它们来获得实际的具体好处。