The ease with which callbacks can be created leads people to create them carelessly and excessively. While I like what the article has to say, there are ways to write callback heavy code that do not get ugly so fast. Looking at the iOS nested block example from Marco Arment -- the first step is to not do everything inline. Then the code suddenly becomes clear and the argument becomes one of syntax sugar.
Comparing callbacks to goto is a tad unfair. They don't merely solve async issues, but also event handling and dynamic systems to name two common uses. I don't see a better solution on the table. Using callbacks to write deeply async code is the real problem. And while async/await may help with this problem, it still won't tell you why step 3 never finishes, because it's still waiting for a come from.
First: code that performs simple sequential steps should look simple. With callbacks, it always ends up looking complicated.
Second: refactorability in callback oriented code is a lot worse than linear code. Even refactoring code with a single callback can be annoying. Async code with callbacks that looks and feels like imperative synchronous code is an enormous gain.
First: you're hammering the async point, which I don't disagree with. I am just pointing out that you can write less horrible async code than the example cited with callbacks.
Second: wait until people write ludicrous numbers of async routines as if they were imperative because it's so easy. Calling one from another (and hooking them up to event handlers). You'll have the same damn problem one level removed.
Code that performs simple sequential steps should be synchronous.
Keep the asynchronous complications at the code that perform non-sequential steps. And yes, I'm fully aware that some libraries (Javascript's one, the guilty are always the same few) force you to use asynchronous calls. That's a flaw of the library.
Comparing callbacks to goto is a tad unfair. They don't merely solve async issues, but also event handling and dynamic systems to name two common uses. I don't see a better solution on the table. Using callbacks to write deeply async code is the real problem. And while async/await may help with this problem, it still won't tell you why step 3 never finishes, because it's still waiting for a come from.