TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Why are callbacks more “tightly coupled” than promises?

65 pointsby rdfiabout 11 years ago

9 comments

jasallenabout 11 years ago
This is not a very good or complete answer as others are pointing out.<p>Promises allow you to make your async call in a context where you <i>don&#x27;t know</i> what has to be done next. You pass the promise around and attach to it as needed (and chained if necessary), <i>that</i> is the lack of coupling that is so desirable.
评论 #7361298 未加载
评论 #7360879 未加载
评论 #7363066 未加载
ollysbabout 11 years ago
As I mentioned in the comments, those examples aren&#x27;t actually equivalent, the callback version could be:<p><pre><code> var getData = function(callback){ showLoadingScreen(); $.ajax(&quot;http:&#x2F;&#x2F;someurl.com&quot;, { complete: function(data){ hideLoadingScreen(); callback(data); } }); }; var loadData = function(){ getData(doSomethingWithTheData); } var doSomethingWithTheData = function(data){ &#x2F;&#x2F;do something with data };</code></pre>
评论 #7360822 未加载
评论 #7361357 未加载
batterseapowerabout 11 years ago
Thinking about this from a Haskell perspective, it seems that with promises the lambda waiting for the callback is basically encapsulated into the promise:<p><pre><code> type Promise a = (a -&gt; IO ()) -&gt; IO () getData :: Promise String </code></pre> Whereas with callbacks you pass that around explicitly:<p><pre><code> getData :: (String -&gt; IO ()) -&gt; IO () </code></pre> Promises are a monad, so you get the usual monad advantages of being able to &quot;hide the plumbing&quot; behind the abstraction, hence no tower of explicit callbacks in your JS code.<p><pre><code> instance Monad Promise where return x = \k -&gt; k x fmap f p = \k -&gt; p (k . f) mx &gt;&gt;= fxmy = \k -&gt; mx (\x -&gt; fxmy x k)</code></pre>
评论 #7362565 未加载
评论 #7362017 未加载
lightbladeabout 11 years ago
I like harpo&#x27;s answer better than the accepted answer. I&#x27;ll help generate more upvote for that answer from here :)<p>&gt; The coupling is looser with promises because the operation doesn&#x27;t have to &quot;know&quot; how it continues, it only has to know when it is ready.<p>&gt; When you use callbacks, the asynchronous operation actually has a reference to its continuation, which is not its business.<p>&gt; With promises, you can easily create an expression over an asynchronous operation before you even decide how it&#x27;s going to resolve.<p>&gt; So promises help separate the concerns of chaining events versus doing the actual work.
lhorieabout 11 years ago
Here&#x27;s a contrived example:<p>Promises:<p><pre><code> &#x2F;&#x2F;model User.get = function() { return getData(); }; User.getOdd = function() { return User.get().then(filterOdd); }; &#x2F;&#x2F;controller someControllerAction = function() { User.getOdd().then(redirectToHomepageIfEmpty); }; </code></pre> Callbacks:<p><pre><code> &#x2F;&#x2F;model User.get = function(callback) { getData(callback) } User.getOdd = function(callback) { User.get(function(data) { if (typeof callback == &quot;function&quot;) { callback(filterOdd(data)); } }); }; &#x2F;&#x2F;controller someControllerAction = function() { User.getOdd(redirectToHomepageIfEmpty) }; </code></pre> Notice how there&#x27;s a little bit of noise required in the callback version of User.getOdd - i.e. if (typeof callback == &quot;function&quot;). Ideally this kind of noise is something that should be hidden at a framework level, and not show up in application code.<p>Noise can get quite significant when the code is predominantly dealing with asynchrony, e.g. try implementing this in callback style:<p><pre><code> jQuery.when(User.getOdd(), Pinterest.search(&quot;something&quot;)).then(doSomething) </code></pre> It&#x27;s doable, but it&#x27;s messy, because the code that is supposed to be focused on pinterest items and odd users now also needs to deal with flags indicating which http request is done at which point.
taericabout 11 years ago
I&#x27;m not sure this makes a strong case. Especially since in this case the callback could be &quot;simplified&quot; by having it such that the callback example looks like:<p><pre><code> void loadData = function(){ showLoadingScreen(); $.ajax(&quot;http:&#x2F;&#x2F;someurl.com&quot;, { complete: hideLoadingScreen(function(data){ &#x2F;&#x2F;do something with the data }) }); }; </code></pre> Where hideLoadingScreen is simply:<p><pre><code> function hideLoadingScreen(f) { return function(e) { f(e); doHide(); }; } </code></pre> You could probably take this further. Though, I&#x27;m not sure how valuable that is.
评论 #7360582 未加载
fleitzabout 11 years ago
It&#x27;s about reification...<p>Callbacks are an implementation of asynchronous processing each slightly different sort of like &#x27;function calls &#x2F; calling convention&#x27; in assembler, while promises provide a reified interface that is easier to think about conceptually because you&#x27;re thinking about what to do, not how to do it.<p>The contrived example in SO can just as easily be decoupled while still using callbacks, however the promise based code &#x27;looks&#x27; better because it more concisely describes what&#x27;s going on in terms of &#x27;english&#x27;.
y1426iabout 11 years ago
Here&#x27;s an example which might explain the decoupling a bit:<p><pre><code> &#x2F;&#x2F; You may call this syntactic sugar var p1 = new Promise(function(response, reject) { setTimeout(function(){ response(Math.random() * 1000); }); }).then(function(val){ console.log(val); return val; }); &#x2F;&#x2F; But here&#x27;s the magical decoupled call p1.then(function(val) { console.log(val); });</code></pre>
pacaroabout 11 years ago
I can&#x27;t work out if this is an “Async Tarpit” or an instance of the “Blub Paradox”<p>Callbacks vs. Promises vs. Futures - they can all express the same things - personally I like promises, but YMMV