Live data from Hacker News

Escape from Callback Hell

ianbishop.github.com

11–20 of 86 posts

Re: Escape from Callback Hell

#11
Deferreds are cool although they have their own set of issues. Mainly, that when you start chaining them there are situations where it can be a bit counterintuitive what is going on. My background is the Deferred from Twisted and Reimplemented in MochiKit.

You really need to read the Deferred implementation if you are going to use it. Otherwise you are asking for trouble long term. Of course, the other issue is that you may run into challenges explaining deferred's to your co-workers. :)

Twisted explored some cool ideas where you basically would write asynchronous code in an interative style using a blend of iterators and generators. Sadly until Javascript has those capabilities in every browser (and not just Firefox) I don't think it is possible.

Re: Escape from Callback Hell

#12
post #11

Deferreds are cool although they have their own set of issues. Mainly, that when you start chaining them there are situations where it can be a bit counterintuitive what is going on. My background is the Deferred from Twisted and Reimplemented in MochiKit. You really need to read the Deferred implementation if you are going to use it. Otherwise you are asking for trouble long term. Of course, the other issue is that…

Particularly Twisted's inlineCallbacks (http://twistedmatrix.com/documents/current/api/twisted.inter...) are really nice. They are so nice, they actually completely offset all the other unpleasantness I experiance from Twisted.

Re: Escape from Callback Hell

#13
Well, frankly, it looks like you're jumping from one sheep to another. Using deferreds does NOT make more sense, and is actually even more difficult to perceive as it's quite counter-intuitive. MVVM is the way to go for web apps. Actually, anything else would be better than this.

The methods and approaches jQuery provides should not be used as a mainframe to achieve your goal, they should only be used as helpers here and there if ever.

Re: Escape from Callback Hell

#14
The main issue I have with "escaping from callback hell" is that it's a half-truth. Although I don't know much about how the Reactive Framework created by Microsoft works, I know they went well beyond the basics to try to make it all-encompassing coming closer to making it a full-truth.

Just transmitting data back and forth may play well to the strengths of your abstraction. But we have other uses with Timers that should also need such abstractions.

With Timers I have other needs like delaying the execution, resetting the delay countdown, stopping it before it executes it at all (like cancelling it), and finally with an Animation class I needed a way to finish executing a string of events in an instant in order to start a new animation. Also the Animation had other Animation versions at play that could need to be sped up before a new Animation started.

In .NET they seem to have a handy feature that waits the code to run before proceeding that comes into play with their .NET version of the Reactive Framework.

As far as I can tell, it's tough to really solve it. JavaScript doesn't have extra features like .NET does. We are more limited in what we can do. In Dart they have a version of this called Future that has been streamlined recently. As simple as it may seem to be, it comes with other related abstractions called Streams that altogether make it a bit daunting to escape from that hell only to land on the fire outright.

Re: Escape from Callback Hell

#15
post #6
post #2

I honestly find "callback hell" a lot easier to follow and understand than the vast majority of fixes everyone is coming up with. They're just continuations, seriously, what's everyone's problem? You define a function, it gets access to the current scope, it defines the rest of the program flow. If you feel like your code is nesting too deep, you define the function elsewhere and just reference it by name. Then you d…

It's not difficult, it's just gross. And these promises don't solve the main problem, which is that synchronous functions return the result, until at some point you add some IO, so now it takes a callback. And everything that calls it now has to take a callback. And hours later all you've done is add a network call in some basic function but your diff looks like a total re-write.

That is not the main problem, that is you making a change with huge implications.

The big problem with callbacks is that they hold dynamic state and behaviour but, unlike other dynamic (and many static) objects in most languages, do not offer any interfaces to manipulate and reason about them. That's what higher level abstractions like promises provide.

Re: Escape from Callback Hell

#16
post #3

It's a real shame to have a language this high level, yet still have to go through this much crap just to get things done. Manual memory management is easier than this. But while including GC in the runtime has it's drawbacks, there is no reason that a language can't just handle task switching for you (like Go does, for example).

IMHO the event model / callback spaghetti / what-have-you is tricky precisely because it operates at a high level of abstraction.

Memory management, by comparison, is conceptually simpler because... well... the concept is simple. Allocating and de-allocating resources, while tricky at scale, is something for which everyone (including non-programmers) probably have existing mental models for.

Event driven programming, on the other hand, is a slippery high level concept. There are relatively few analogues for it in the "real world", and therefore requires additional mental gymnastics to internalize and understand.

Essentially, we need to 1) follow the execution pattern of event driven code (annoying), while at the same time 2) "visualizing" or conceptualizing a fairly un-natural manner of abstraction.

Re: Escape from Callback Hell

#17
post #5

A great library for structuring your callbacks is "async": https://github.com/caolan/async I've only used it with node.js, but it's supposed to work in web browsers as well. It allows you to think a little more procedurally ("waterfall" is especially handy here) while writing CPS code. Very good.

I have used it in browser games to load assets (images, sounds, data files) before starting a new state (menus, gameplay, etc). It's a fantastic library.

Re: Escape from Callback Hell

#18
post #6
post #2

I honestly find "callback hell" a lot easier to follow and understand than the vast majority of fixes everyone is coming up with. They're just continuations, seriously, what's everyone's problem? You define a function, it gets access to the current scope, it defines the rest of the program flow. If you feel like your code is nesting too deep, you define the function elsewhere and just reference it by name. Then you d…

It's not difficult, it's just gross. And these promises don't solve the main problem, which is that synchronous functions return the result, until at some point you add some IO, so now it takes a callback. And everything that calls it now has to take a callback. And hours later all you've done is add a network call in some basic function but your diff looks like a total re-write.

A function that doesn't do IO and a function that does IO sound like totally different functions to me. Why aren't you writing a new function?

Re: Escape from Callback Hell

#19
post #15
post #6

Earlier quoted context omitted.

It's not difficult, it's just gross. And these promises don't solve the main problem, which is that synchronous functions return the result, until at some point you add some IO, so now it takes a callback. And everything that calls it now has to take a callback. And hours later all you've done is add a network call in some basic function but your diff looks like a total re-write.

That is not the main problem, that is you making a change with huge implications. The big problem with callbacks is that they hold dynamic state and behaviour but, unlike other dynamic (and many static) objects in most languages, do not offer any interfaces to manipulate and reason about them. That's what higher level abstractions like promises provide.

> but, unlike other dynamic (and many static) objects in most languages, do not offer any interfaces to manipulate and reason about them

Sure they do. You just need to start thinking of javascript as a functional language and all this stuff becomes much ... simpler.

First of all, why would you even need to reason about a function's internal state? That's a sign of a leaky abstraction.

Furthermore, every time you want to manipulate the internal state of a function, what you're really after is defining a better API to provide arguments to said function.

And if you still for some reason need to dick around with a function's internal state, just use partial function application.

Re: Escape from Callback Hell

#20
post #2

I honestly find "callback hell" a lot easier to follow and understand than the vast majority of fixes everyone is coming up with. They're just continuations, seriously, what's everyone's problem? You define a function, it gets access to the current scope, it defines the rest of the program flow. If you feel like your code is nesting too deep, you define the function elsewhere and just reference it by name. Then you d…

This is what I have being thinking. These proposals for ways to refactor always back themselves up by using actual use case examples of callbacks vs toy examples of their fix

"there! See how much cleaner that is?"

No, I don't, and this stories solution in particular, is particularly ugly.

Post reply on HN