Live data from Hacker News

Callback Hell (2016)

callbackhell.com

101–110 of 170 posts

Re: Callback Hell (2016)

#101

Earlier quoted context omitted.

Maybe it's because I'm a C programmer and not familiar with js but I felt this article did a very poor job of describing "callback hell." I still don't have a clear idea of what it is. The author shows some code with lots of nested if/else clauses and claims this is bad because it blocks; fair enough. Then they explain what callbacks are and that some people have trouble understanding the asynchronous nature. Then th…

I believe the primary issues are a mistaken belief that "every line of code that gets executed should be read from top to bottom in the same order" (an issue with any code that isn't modular) and the debugging issue of using anonymous functions defined inline. Readability of code is very important. Inline callback definitions hurt this.

Extracting inline callbacks leads to indirection, especially if you're only extracting to avoid indentation. It doesn't make the code simpler or easier to follow.

Promises and especially async/await let you read code top to bottom once more, with other benefits like monad chains that catch synchronous failure.

Re: Callback Hell (2016)

#102
post #91

This is where syntactic sugar can be helpful. CoffeeScript can make the example a lot more readable by removing the unnecessary braketing when the last argument of a function is a callback (common case in node.js). The only thing that's still ugly is the .bind() applied to a function, which somewhat messes with the style. Other than that, this makes callbacks flow a lot more naturally when reading source code. (Of co…

Use '=>' instead of '->' to automatically bind 'this'.

Re: Callback Hell (2016)

#103
post #49

The 'asynchonous problem' in JS is twofold. It makes it more difficult to reason about the program, and is hell on readability, and readbility matters. Support, maintenance, etc. The lack of an ability to structure async ops in a simple way is the biggest drawback in the language. Callbacks of course have the drawbacks mentioned. Sure, you can separate the functions, smaller functions and that too is preferred, but s…

I can't wait for async/await to be added to node is proper!

Re: Callback Hell (2016)

#104
post #6

> In other languages like C, Ruby or Python there is the expectation that whatever happens on line 1 will finish before the code on line 2 starts running and so on down the file. As you will learn, JavaScript is different. A lot of beginner guides to various programming languages make this mistake of associating a certain property with a language as if it's inherent. In this case, async code - while sold as a main fe…

> This may seem a nitpick, but I think it's an incredibly important distinction for beginners (or at least, I think it's incredibly important not to mislead beginners into believing in this limitation early on).

No, I think it's very important, maybe even more important for some of us old dogs still marvelling at having virtual SMP in a desktop rig. While it might be easier to teach people new to programming the old model of a series of instructions that goes step by step, I feel it's also important to express that statements may get run out of order, even in languages not designed for it (optimizing compilers have been doing this forever).

> While bombarding beginners with a lot of info at the start is a bad idea, these kind of misconceptions can be very damaging. They leads to a very narrow idea of what's possible with (any) languages in general, and uninformed decisions on what to learn as a result.

It's also dangerous to always assume that statement A will execute before B just because that's how they appear in the code. Getting people acquainted with the tools necessary to properly do "threading" early on would be a step in the right direction.

Re: Callback Hell (2016)

#105
post #101

Earlier quoted context omitted.

I believe the primary issues are a mistaken belief that "every line of code that gets executed should be read from top to bottom in the same order" (an issue with any code that isn't modular) and the debugging issue of using anonymous functions defined inline. Readability of code is very important. Inline callback definitions hurt this.

Extracting inline callbacks leads to indirection, especially if you're only extracting to avoid indentation. It doesn't make the code simpler or easier to follow. Promises and especially async/await let you read code top to bottom once more, with other benefits like monad chains that catch synchronous failure.

Any one section of code should have a "need to know" format. While you want to know "what's happening" in order of execution, having all the "how it's happening" code shouldn't be necessary.

For example, you want to know that the code is about to "getAccountData" but you shouldn't need to know how. You see that it is called, and you see that afterward, a callback called "loadAccountDataInReport" will be called. Why should you see all the guts of those two functions inline?

Re: Callback Hell (2016)

#106
post #6

> In other languages like C, Ruby or Python there is the expectation that whatever happens on line 1 will finish before the code on line 2 starts running and so on down the file. As you will learn, JavaScript is different. A lot of beginner guides to various programming languages make this mistake of associating a certain property with a language as if it's inherent. In this case, async code - while sold as a main fe…

If I accept your claims that the distinction is important, and that misconceptions can be damaging, is the actual implication here doing any actual damage? Is what you're talking about relevant to this article or to JavaScript?

The fact of the matter is that JavaScript was born with first class functions and event handlers, from the very beginning. In the browser, the majority of projects of any substantial size involves using event handlers, AJAX requests and requestAnimationFrame/setTimeout, among other things.

Even on NodeJS, if you're serving something you're using async. If you're interacting with process events, you're using async. If you're reading files, you're using async. (even the sync functions for files wrap async ones) If you've downloaded anything from NPM, you're almost certainly using async. There is next to nothing that is pure synchronous.

Even if what you said is true, you are suggesting a misconception that could be damaging in the name of avoiding damaging misconceptions. Almost all real world usage of JavaScript uses async code & callbacks, and to split hairs over whether async is native to the language for the sake of beginners is to mislead them.

Re: Callback Hell (2016)

#107
post #99
post #6

> In other languages like C, Ruby or Python there is the expectation that whatever happens on line 1 will finish before the code on line 2 starts running and so on down the file. As you will learn, JavaScript is different. A lot of beginner guides to various programming languages make this mistake of associating a certain property with a language as if it's inherent. In this case, async code - while sold as a main fe…

Are there JS runtimes that are primarily synchronous? Certainly not any popular/widely used ones. Asynchrony is for all practical purposes a property of JS.

I'm not even sure there's an implementation that could do even the most common synchronous operation.

Like opening a socket, sending data, and blocking on the response.

Re: Callback Hell (2016)

#108
post #101

Earlier quoted context omitted.

Extracting inline callbacks leads to indirection, especially if you're only extracting to avoid indentation. It doesn't make the code simpler or easier to follow. Promises and especially async/await let you read code top to bottom once more, with other benefits like monad chains that catch synchronous failure.

Any one section of code should have a "need to know" format. While you want to know "what's happening" in order of execution, having all the "how it's happening" code shouldn't be necessary. For example, you want to know that the code is about to "getAccountData" but you shouldn't need to know how. You see that it is called, and you see that afterward, a callback called "loadAccountDataInReport" will be called. Why s…

Now let's say you're in a route handler where the buck stops, and you need to compose any number of async calls, some branching on if-else logic and/or the results of other async calls.

This is where the "just wrap it" argument breaks down.

Though I think promises are only slightly better when you have if-else branches that add to the async chain. It's not til async/await where Javascript finally hits its stride.

Re: Callback Hell (2016)

#109
post #91

This is where syntactic sugar can be helpful. CoffeeScript can make the example a lot more readable by removing the unnecessary braketing when the last argument of a function is a callback (common case in node.js). The only thing that's still ugly is the .bind() applied to a function, which somewhat messes with the style. Other than that, this makes callbacks flow a lot more naturally when reading source code. (Of co…

I absolutely disagree. Brackets are a big part of the reason the JS version is more readable than the CoffeeScript version, IMO. I don't understand why anyone would think readability would increase with syntactical ambiguity. This isn't even the traditional braces-vs-indentation argument either; I much prefer Python's syntax to CoffeeScript's, and I use both regularly.

Re: Callback Hell (2016)

#110
post #29

As a C programmer working with a large codebase, I have come to HATE callbacks. Seriously, the worst feeling ever is tracing through a huge function tree, only to run into function pointer dereference. Then you have to go on a wild goose chase to find out when, where and what it will be assigned to. STATIC TYPES PEOPLE.

C/C++ callbacks are fairly different in practice than what the article is talking about. You might like callbacks in JavaScript. You might really like promises -- no wild goose chase to track down the chain, because promises chain things explicitly and make async code look more synchronous.

What's most interesting about your point is that what the article suggests -- naming and de-nesting callbacks -- is in a way what you're warning against. By naming it and physically moving it, execution that was contained within a single block of code is now jumping around, and can move to other places where you have to go looking.

Even though it's considered an anti-pattern for good reasons, there are some advantages to nested callbacks.

Post reply on HN