Live data from Hacker News

Escape from Callback Hell

ianbishop.github.com

61–70 of 86 posts

Re: Escape from Callback Hell

#61
post #57
post #39

> "This is better, it definitely makes it clearer what exactly is going on" function createItem(item, successCallback, errorCallback) { var req = $.post("/api/item", item); req.success(successCallback); req.error(errorCallback); } How is this more clear than the default jQuery $.post?

Not really better. The advantages of promises show up when you pass promises around, letting other people add their callbacks to it (this way the "callback structure" is implicit from the program flow, just like what happens when you do normal sync programming. Another advantage of promises is that they have some better support for error handling (you don't need to thread the error handler around and you "throw" stat…

The named functions were just an attempt at better highlighting what is going on for some readers. Not sure if it worked, but sorry it annoyed you :).

Re: Escape from Callback Hell

#62
post #19
post #15

Earlier quoted context omitted.

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…

You need to reason about async operations when for example you need to do something when multiple async operations have completed; even more often if some may have failed.

If all you have to implement async operations are plain callbacks then yeah, they are not really an abstraction of anything, and you can probably call them 'leaky'. Which is why you need to create real abstractions around them, like promises.

I think we basically agree.

Re: Escape from Callback Hell

#63
post #41

Earlier quoted context omitted.

Then that's a breaking change of the someBigFunction()s interface and it should be treated with care, not just quickly patching on a promise and hope for the best. Javascript is single threaded so when you wrote someBigFunction() you didn't have to think of parallel side effects. If you suddenly pause the execution of someBigFunc() and allow the user to mess around with the interface, the global state that someBigFun…

The fact that I changed a calculation from a constant to reading its value from indexeddb shouldnt need to be an intrusive change. It is makes things more likely to break, there isnt some 'oh you decided to do io so you deserve to do a big refactor' point

And this is why handling state in imperative programs is such a mess. You are fundamentally changing the way state is treated in that application - why shouldn't it require a massive refactor?

Re: Escape from Callback Hell

#64

Earlier quoted context omitted.

The fact that I changed a calculation from a constant to reading its value from indexeddb shouldnt need to be an intrusive change. It is makes things more likely to break, there isnt some 'oh you decided to do io so you deserve to do a big refactor' point

And this is why handling state in imperative programs is such a mess. You are fundamentally changing the way state is treated in that application - why shouldn't it require a massive refactor?

Functional programs don't make this easier.

And don't say "monad transformer stacks" somehow solve this problem in an easier way.

Re: Escape from Callback Hell

#65
post #44

Earlier quoted context omitted.

Not conceptually. From the perspective of the rest of the program, isPrime(x) has no side effect regardless of which method you use to implement it. If you are working in a purely functional language, then it makes sense to have introducing IO be a major change, as it has huge potential to make a function impure, and assuming IO is a pure function is roughly the equivalent of unsafePerformIO. However, in this case, w…

Of course it's different. What if the IO fails?

What if pure code throws an Exception?

If every function is effectively impure, it still sucks.

Re: Escape from Callback Hell

#66
post #56
post #24

My favorite solution to this problem is a thing the OKCupid developers made called IcedCoffeeScript http://maxtaco.github.com/coffee-script/

Do you know if there are any good alternatives that are pure-ish JS? I know that same guy worked on tamejs but they don't seem to be working on that anymore...

There's tame.js from the same guys (https://github.com/maxtaco/tamejs)

Re: Escape from Callback Hell

#67
post #64

Earlier quoted context omitted.

And this is why handling state in imperative programs is such a mess. You are fundamentally changing the way state is treated in that application - why shouldn't it require a massive refactor?

Functional programs don't make this easier. And don't say "monad transformer stacks" somehow solve this problem in an easier way.

Haskell definitely makes it easier. You can use preemptive green threads with almost all the ease of cooperatively multitasked code because of the prevalence of immutability.

You get the performance benefits of non-blocking code. The simplicity benefits of blocking code. And (almost) none of the threading hell you get in imperative languages.

Re: Escape from Callback Hell

#68
I just don't understand the issue people are having here. Nested callbacks are a design choice, if you do not want nested callbacks stop writing code with them in it.

Here is a simple example in some Node.js code I've just written (I've never written any before this little project).

https://github.com/Offler/node-bundler/blob/master/lib/bundl...

As you can see you just need to write in an OO manner and use function.bind(this) and Bob's your uncle. Really don't get the difficulty.

Re: Escape from Callback Hell

#69
post #64

Earlier quoted context omitted.

And this is why handling state in imperative programs is such a mess. You are fundamentally changing the way state is treated in that application - why shouldn't it require a massive refactor?

Functional programs don't make this easier. And don't say "monad transformer stacks" somehow solve this problem in an easier way.

Not necessarily because it is functional, but Erlang makes this vastly easier.

I find the "oh you changed tiny piece of logic, you should totally have to refactor every line of code that follows it" very strange. It obviously sucks, there are far better ways to handle it and they are slowly making it into the language.

Re: Escape from Callback Hell

#70
post #57

Earlier quoted context omitted.

Not really better. The advantages of promises show up when you pass promises around, letting other people add their callbacks to it (this way the "callback structure" is implicit from the program flow, just like what happens when you do normal sync programming. Another advantage of promises is that they have some better support for error handling (you don't need to thread the error handler around and you "throw" stat…

The named functions were just an attempt at better highlighting what is going on for some readers. Not sure if it worked, but sorry it annoyed you :).

I personally find that creating too many functions makes the code look too different from the "natural", synchronous alternative. But I also hate when people write tons of 1-line methods (Uncle Bob style) so YMMV.
Post reply on HN