5 ms·
This is a good overview of promises and async / await. The initial thesis of this seems to be that you need promises or async / await to avoid callback hell whi
by BinaryIdiot 10y ago
This is a good overview of promises and async / await. The initial thesis of this seems to be that you need promises or async / await to avoid callback hell which I disagree with. You can still write good code, not use promises or async / await and not run into callback hell.
The example given in the article of callback hell isn't even a very good one. Why are we using an asynchronous method to fetch users, another asynchronous method to filter them and yet a third one to get their likes and return those. If that's the ultimate goal then, depending on your backend, you can should be able to make that in a single call.
But let's ignore the poor example in the article. Let's say we need to make 3 calls to 3 asynchronous functions and the result ultimately needs to be returned after all 3 functions are finished executing. Do you just nest them like the article? Absolutely not.
Essentially my point is: you can always architect around callback hell and make it better. I've already gotten into projects where I would now consider them "promise hell" where every method returns a promise of a promise of a promise of a promise of a promise and it's just maddening to debug.
Alternatives to callback hell are always context specific. There is no one-shot-cure-all, in my opinion (not even promises or async / await) but there are plenty of steps you can take.
- Can I separate or combine at least two of these asynchronous functions?
- Can I use a pseudo parallel or serial processing pattern ala async.js?
- Can I use a messaging pattern where each message is handled separately with a single callback ala msngr.js or postal.js?
- Can I simply create a response building pattern where many asynchronous methods write to the same response object and, when it's complete, return it?
- Does it make sense to use a promise here? What about the async / await pattern?
- recursive 10y agoI'm pretty new at promises, but doesn't any appearance of a "promise of a promise" indicate a trivial mis-use of promises? Isn't the whole point of promises that they can be chained together without nesting?
- pandler 10y agoThat was my thought as well. A promise that returns a promise that returns a value is no different than a promise that returns a value.
- supster 10y agoexactly, I'm not sure why you would be having promises of promises
- phpnode 10y ago> Isn't the whole point of promises that they can be chained together without nesting? Yes, it's an excedingly common misunderstanding and probably one of the main causes of people being "turned off" by promises. It's kind of frustrating to see so many blog posts making this mistake when critiquing them.
- vog 10y agoIndeed. And if you generalize this idea only slightly, you get ...... monads! Maybe promises will be the vehicle that makes understanding the usefulness of monads available for the masses. Alternatively, promises may fail the acceptance test for the same reason as monads - because the average developer simply doesn't care / doesn't get it. I really hope for the first scenario, though.
- pekk 10y agoIf you are not trying to use Haskell (which has monads as a workaround for certain problems) then what is the point having monads? The average developer doesn't care because they are working in an environment where monads aren't needed. Trying to drag monads into arbitrary languages like Javascript isn't some kind of best practice, it's cargo culting.
- deleted 10y ago[deleted]
- andrewflnr 10y agoA Monad is a general-purpose mathematical structure, not just a workaround. GP gave you an example of something they're useful for, which you completely ignored.
- berdario 10y agoWhat's the point of having monads? You might as well ask what's the point of having Iterable<> when you're programming in C :) It's not that you strictly _need_ monads or Iterable interfaces, it's that they represent an abstract concept which allows you to solve problems in a generic and type-safe way I wouldn't probably "drag monads" into Javascript, but I'd surely appreciate Functors when programming in Javascript :)
- adrusi 10y agoHaskell doesn't have monads as a work-around. They are a useful abstraction because they capture a common semantic pattern found in many programming concepts. Nullable types, error handling, sequential execution, and asynchronous event handling are all concepts that can be described monadically. By describing them as monads and making the monadic pattern a core idea of the language, you can write algorithms that operate on any monad, so that you can write one function and have it be useful for both managing the execution of IO and error handling in a generic way. People have an aversion to monads because a the concept of a monad has no grounds in reality, kind of like complex numbers. It is an abstraction that is useful not because it describes anything, but because it is simply a useful way to think.
- BinaryIdiot 10y agoCorrect but once you get some functions returning promises and other functions returning actual values then your own code base can become confusing. I constantly find myself in these types of code bases trying to find function definitions so I know what it returns. You can try and make 100% of your asynchronous methods return promises but what happens when you need to work with a library that can't use promises? Do you write a callback for that? Now you have a mixture and sure a few of these no big deal but when the code base balloons and you start having one offs all over the place now you need to figure out what returns what and code specifically to that. Maybe if promises were in ECMAScript from the beginning then everyone would have used them and it wouldn't be a huge deal but right now it can get a bit frustrating, in my opinion. The stack traces of these nested promises are never fun to dive into as well though that likely depends on whether you're using a polyfill or not.
- atomwaffel 10y agoI'm not quite sure I understand you, but it sounds like a case for `Promise.resolve(value)`[1] – that's what I do whenever I don't know if something will be a Promise or an already-resolved value. `Promise.resolve(value)` returns a Promise that immediately resolves with `value` or whatever `value` resolves to if it's a Promise – no need to do any checks yourself, no need to nest Promises inside Promises inside Promises. For example, imagine you have a charting library and you want to draw a chart, but you don't know if the data is available already or if it's being loaded asynchronously. You can just write: // `drawChart(data)` is a synchronous function // `data` may be the data itself or a promise that resolves to the data Promise.resolve(data).then(drawChart) For me, this is actually the killer feature of Promises, avoiding callback hell is just a nice side-effect. Once you start thinking of Promises as placeholders for values that may or may not be known already (rather than just an abstraction of the `callback(err, value)` pattern), you can write some really elegant code. [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
- BinaryIdiot 10y agoFair enough that would take care of my issue for the most part. Native implementations of promises should work well with that. Seems most of the polyfills end up using setTimeout() which is kinda slow[1] and one of the reasons I don't typically like working with them (waiting for more ubiquitous support). Thanks for the info! [1] http://www.krissiegel.com/rants/2015/11/7/settimeout-sucks http://www.krissiegel.com/rants/2015/11/7/settimeout-sucks
- drinchev 10y agoWhat I think people sometimes forget about async/Promises vs callbacks is that callbacks-style define a code structure that is hard to maintain by multiple developers, since it leaves a lot of power to the way you write your code. Not every team has 5 experienced JS developers, so at one point implementing a small feature by a team member would become : `Hey, let's just nest another callback in there. It takes 1 line of code` instead of implementing it in a readable way. Promises solve this, but indeed there are a couple of problems there with debugging. Honestly I think they give more readable code than whatever callback implementation you invent to avoid the callback hell. Libraries as bluebird can make your promise operations really short and even one liners, without performance hit. Finally now we have async, which I hope will be popular enough in the future to become at least as much popular as Promises are now.
- dvlsg 10y agoEven when implemented in a readable way, callbacks can still become hard to maintain. When you use properly separate functions (instead of anonymous ones), you typically have to embed those methods inside one another. I'll take an example from the callbackhell website that was linked previously: document.querySelector('form').onsubmit = formSubmit function formSubmit (submitEvent) { var name = document.querySelector('input').value request({ uri: "http://example.com/upload", body: name, method: "POST" }, postResponse) } function postResponse (err, response, body) { var statusMessage = document.querySelector('.status') if (err) return statusMessage.value = err statusMessage.value = body } What happens when I want to do something other than `postResponse` when `formSubmit` is finished? I would have to start thinking about using partial application and providing specific callbacks, which is okay, but what if the callback levels are multiples deep? The code still starts to get muddy really quickly. With promises / async, the asynchronous code doesn't need to know anything about what functions want to run afterwards, so the concerns stay completely separated.
- drinchev 10y agoExactly. You need to keep really good control over your code structure to avoid callback hell. And again at one point you will end up in a situation where you will need to declare functions inside a main function, etc. That's why I noted that I've never seen a callback implementation that is more readable than promises.
- coldtea 10y ago>This is a good overview of promises and async / await. The initial thesis of this seems to be that you need promises or async / await to avoid callback hell which I disagree with. You can still write good code, not use promises or async / await and not run into callback hell. Even if you could, you shouldn't. It's busy work -- manually doing the computer's work.
- emodendroket 10y agoI agree that you don't need them, but I do think it makes life easier.