javascript 为什么回调比承诺更“紧密耦合”?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21141817/
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
Why are callbacks more "tightly coupled" than promises?
提问by Revious
Can you explain me the following phrase (taken from an answer to Stack Overflow question What are the differences between Deferred, Promise and Future in Javascript?)?
你能解释一下下面的短语吗(摘自对 Stack Overflow 问题的回答Javascript 中的 Deferred、Promise 和 Future 之间有什么区别?)?
What are the pros of using jQuerypromises against using the previous jQuery callbacks?
使用jQuery承诺与使用以前的 jQuery 回调相比有什么优点?
Rather than directly passing callbacks to functions, something which can lead to tightly coupled interfaces, using promises allows one to separate concerns for code that is synchronous or asynchronous.
不是直接将回调传递给函数,这会导致紧密耦合的接口,使用 Promise 允许人们分离同步或异步代码的关注点。
采纳答案by Olmo
I don't think promises are more or less coupled than callbacks, just about the same.
我不认为 Promise 与回调或多或少耦合,几乎相同。
Promises however have other benefits:
然而,Promise 还有其他好处:
If you expose a callback, you have to document whether it will be called once (like in jQuery.ajax) or more than once (like in Array.map). Promises are called always once.
There's no way to call a callback throwing and exception on it, so you have to provide another callback for the error case.
Just one callback can be registered, more than one for promises, and you can register them AFTER the event and you will get called anyway.
In a typed declaration (Typescript), Promise make easier to read the signature.
In the future, you can take advantage of an async / yield syntax.
Because they are standard, you can make reusable components like this one:
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(....));
如果公开回调,则必须记录它是被调用一次(如在 jQuery.ajax 中)还是多次(如在 Array.map 中)。承诺总是被调用一次。
无法在其上调用回调抛出和异常,因此您必须为错误情况提供另一个回调。
只能注册一个回调,多个用于承诺的回调,您可以在事件发生后注册它们,无论如何您都会被调用。
在类型化声明 (Typescript) 中,Promise 使签名更易于阅读。
将来,您可以利用 async / yield 语法。
因为它们是标准的,所以您可以制作像这样的可重用组件:
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(....));
More on that: http://www.html5rocks.com/en/tutorials/es6/promises/
更多相关信息:http: //www.html5rocks.com/en/tutorials/es6/promises/
EDIT:
编辑:
- Another benefit is writing a sequence of N async calls without N levels of indentation.
- 另一个好处是编写一个没有 N 级缩进的 N 个异步调用序列。
Also, while I still don't think it's the main point, now I think they are a little bit more loosely coupled for this reasons:
此外,虽然我仍然认为这不是重点,但现在我认为由于以下原因,它们的耦合更加松散:
They are standard (or at least try): code in C# or Java that uses strings are more lousy coupled than similar code in C++, because the different implementations of strings there, making it more reusable. Having an standard promise, the caller and the implementation are less coupled to each other because they don't have to agree on a (pair) of custom callbacks with custom parameters orders, names, etc... The fact that there are many different flavors on promises doesn't help thought.
They promote a more expression-based programming, easier to compose, cache, etc..:
var cache: { [key: string] : Promise<any> }; function getData(key: string): Promise<any> { return cache[key] || (cache[key] = getFromServer(key)); }
它们是标准的(或至少尝试过):使用字符串的 C# 或 Java 中的代码比 C++ 中的类似代码耦合更糟糕,因为那里的字符串实现不同,使其更易于重用。有一个标准的承诺,调用者和实现彼此之间的耦合较少,因为他们不必就具有自定义参数顺序、名称等的(对)自定义回调达成一致......事实上,有许多不同的承诺的味道无济于事。
它们促进了更基于表达式的编程,更容易组合、缓存等:
var cache: { [key: string] : Promise<any> }; function getData(key: string): Promise<any> { return cache[key] || (cache[key] = getFromServer(key)); }
you can argue that expression based programming is more loosely coupled than imperative/callback based programming, or at least they pursue the same goal: composability.
您可以争辩说基于表达式的编程比基于命令式/回调的编程更松散耦合,或者至少它们追求相同的目标:可组合性。
回答by Rui
A promise is an object that represents the result of an asynchronous operation, and because of that you can pass it around, and that gives you more flexibility.
promise 是一个表示异步操作结果的对象,因此您可以传递它,这为您提供了更大的灵活性。
If you use a callback, at the time of the invocation of the asynchronous operation you have to specify how it will be handled, hence the coupling. With promises you can specify how it will be handled later.
如果您使用回调,则在调用异步操作时您必须指定如何处理它,从而产生耦合。使用 promise,您可以指定稍后将如何处理它。
Here's an example, imagine you want to load some data via ajax and while doing that you want to display a loading page.
这是一个示例,假设您想通过 ajax 加载一些数据,同时您想显示一个加载页面。
With callbacks:
带回调:
void loadData = function(){
showLoadingScreen();
$.ajax("http://someurl.com", {
complete: function(data){
hideLoadingScreen();
//do something with the data
}
});
};
The callback that handles the data coming back has to call hideLoadingScreen.
处理返回数据的回调必须调用 hideLoadingScreen。
With promises you can rewrite the snippet above so that it becomes more readable and you don't have to put the hideLoadingScreen in the complete callback.
使用 promise,您可以重写上面的代码片段,使其更具可读性,并且您不必将 hideLoadingScreen 放在完整的回调中。
With promises
带着承诺
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
};
UPDATE:I've written a blog postthat provides extra examples and provides a clear description of what is a promise and how its use can be compared to using callbacks.
更新:我写了一篇博客文章,其中提供了额外的示例,并清楚地描述了什么是承诺以及如何将其使用与使用回调进行比较。
回答by harpo
The coupling is looser with promises because the operation doesn't have to "know" how it continues, it only has to know when it is ready.
使用 promise 的耦合更松散,因为操作不必“知道”它是如何继续的,它只需要知道它什么时候准备好了。
When you use callbacks, the asynchronous operation actually has a reference to its continuation, which is not its business.
当你使用回调时,异步操作实际上有一个对其延续的引用,这不是它的业务。
With promises, you can easily create an expression over an asynchronous operation before you even decide how it's going to resolve.
使用 Promise,您甚至可以在决定如何解决之前轻松地创建一个基于异步操作的表达式。
So promises help separate the concerns of chaining events versus doing the actual work.
因此,promise 有助于将链接事件的关注点与执行实际工作的关注点分开。
回答by edofic
Promises reify the concept of delayed response to something. They make asynchronous computation a first-class citizen as you can pass it around. They allow you to define structure if you want - monadic structure that is - upon which you can build higher order combinators that greatly simplify the code.
Promise 将延迟响应的概念具体化。它们使异步计算成为一等公民,因为您可以传递它。如果需要,它们允许您定义结构 - 即一元结构 - 您可以在其上构建更高阶的组合器,从而大大简化代码。
For example you can have a function that takes an array of promises and returns a promise of an array(usually this is called sequence
). This is very hard to do or even impossible with callbacks. And such combinators don't just make code easier to write, they make it much easier to read.
例如,您可以有一个函数,该函数接受一组 Promise 并返回一个数组的 Promise(通常称为sequence
)。回调很难做到,甚至不可能做到。这样的组合器不仅使代码更易于编写,而且使代码更易于阅读。
Now consider it the other way around to answer your question. Callbacks are an ad-hoc solution where promises allow for clearer structure and re-usability.
现在考虑反过来回答你的问题。回调是一种临时解决方案,其中承诺允许更清晰的结构和可重用性。
回答by Esailija
They aren't, this is just a rationalization that people who are completely missing the point of promises use to justify writing a lot more code than they would write using callbacks. Given that there is obviously no benefit in doing this, you can at least always tell yourself that the code is less coupled or something.
他们不是,这只是一种合理化,那些完全忽略了 Promise 的人用来证明编写比使用回调编写的代码多得多的代码是合理的。鉴于这样做显然没有任何好处,您至少可以始终告诉自己代码耦合度较低或其他什么。
See what are promises and why should I use themfor actual concrete benefits.
看看什么是承诺以及我为什么要使用它们来获得实际的具体利益。