6 ms·
I am surprised to see so much venom against Promises expressed here. I am young, but I began coding (as a profession) just when Angular 1 was popular and I reme
by nawgszy 9y ago
I am surprised to see so much venom against Promises expressed here. I am young, but I began coding (as a profession) just when Angular 1 was popular and I remember callback hell was a real thing.
A few years later, I use Promises a lot, and they work really well. The way errors bubble is logical and easily controlled, it's almost impossible to throw an unhandled promise exception, doing 'parallel' tasks is easy with ```Promise.all([])```, and there's pretty limited complexity with the way a Promise always returns a Promise.
I find the simplest way to use them is to define a class that has a few data properties you'd like to track.
class Handler {
constructor() {
// shared variables can be set / reset here
this.defineInitialState();
}
executeAction() {
return (
this.promiseFn()
.then(() => this.anotherPromise())
.then((passedArgument) => this.promiseExpectingArgument())
.then(
// success case
() => this.successHandler(),
(err) => this.errorHandler()
)
);
}
}
It's modular and you know what to expect (it's always a promise!). Sure, it's imperfect, but I think its weakly opinionated simplicity is a good tradeoff. After all, it makes no distinction of whether any of the functions in that chain were synchronous or not, and that's a nice thing to know. It also makes testing with dummy sync functions in place of actually asynchronous ones a 0-effort integration.
I don't know about this async / await keyword stuff, and if you have to wrap it in a try/catch block, that's unfortunate but also seems like it's not the end of the world. After all, isn't the Go language constantly requiring you to say "if err != nil <your code>"? Explicit error handling isn't even a bad thing.
Anyways, this is just my opinion, it's fair to have your own, and maybe other languages handle asynchronicity more gracefully, but from what I've seen this is a clean way to wrap async OR sync code in a context that makes it always behave predictably and readably.
- djtriptych 9y agoAgreed, it was a HUGE improvement over callback soup. The only cleaner methods I’m familiar with are CSP (as implemented in clojure and go, and to some extent in JavaScript with libraries like RX and Bacon). Basically you’re treating steams of events as first-class values. That’s a rather functional/mathy way to treat concurrency/parallelism but I’ve found it illuminating.
- Lazare 9y ago> I am surprised to see so much venom against Promises expressed here. I am young, but I began coding (as a profession) just when Angular 1 was popular and I remember callback hell was a real thing. The issue with Promises is they could be a LOT better, and they're not for no good reason. Yeah, they're better than callback hell, but anything would be better than callback hell. "Hurts less than stabbing yourself with a screwdriver" should be a baseline expectation, not a recommendation. :)
- nawgszy 9y agoBut how could they "be a LOT better"? I see this being said, but from what I've seen async handling is generally not very graceful; with that said, Promises are a very simple but powerful API that seem to handle the problem fairly elegantly. That is why I'm surprised. I just don't know what the alternative is supposed to be! Can you point me to a language and a library that you would say does a better job of handling asynchronicity than Promises?
- Lazare 9y agoI think this sums of my issues with promises quite well: https://staltz.com/promises-are-not-neutral-enough.html https://staltz.com/promises-are-not-neutral-enough.html
- mercer 9y agoElixir, for one. It's only when I started properly learning other languages than JS that I started seeing how much better a lot of things could be. I say that with a lot of affection for JS, but JS style Promises are among the things that I don't miss. EDIT: To elaborate a bit, what I don't like about (JS) Promises, in hindsight, is that 1) they seem to infect my entire codebase, and 2) making non-async code async is usually nontrivial. In Elixir it's basically a matter of 'telling' a function or an entire module to go do it's thing in another process and report back when done. It means in many cases I only need to change the caller side of things and the code that runs async itself looks the same as the sync code. And that's not even the best part of (Erlang style) processes!
- sushid 9y agoI started programming professionally around the same time but I'm surprised that you think Promise.all([]) makes things easy. IMO Promise.all([]) is nice until you start supporting proper error handling.
- nawgszy 9y agoI'm not sure what you're getting at, can you expand? I work a lot with databases, so say you're trying to write an object and its children in some sort of one-to-many relationship to the DB. You can write a Promise chain like startTransaction() .then(() => writeParent()) .then((children) => Promise.all(children.map((child) => writeChild(child) )) ) .then( // handle success endTransaction(), // handle error cancelTransaction() ) What exactly about that isn't "proper error handling"? Can you expand a bit on how this would be handled differently by you, or perhaps what paradigm you're programming in where Promise.all executes a bunch of items that can't all have the same success and error handler?
- tachang 9y agoCan you explain a bit more what your code is doing? Are you suppose to instantiate the handler class and call it?
- nawgszy 9y agoYeah, exactly. Say you have an API request that is persisting a chunk of data to the database, like a few dependent data items. This way, you write the API request to just be a simple function invocation of the class you instantiated: (req, res, next) => { apiHandler = new APIHandler(args); apiHandler.saveData(req.body) .then( // success () => res.status(200).json(apiHandler.getResponse()), // error () => res.status(400|500).json(apiHandler.getErrorResponse()) ) I mean, it's just a pattern, and I wouldn't necessarily say I use it all the time; it's especially valuable for workers, where you have a series of functions you want to execute where some of them are going to be asynchronous. If you're just making simple create / update / get requests, it's less valuable, and you can just return a Promise from somewhere. Hopefully that gave you an idea of my motivations
- shados 9y agoAs already mentioned, they're a lot better than callbacks (well, for certain cases. There are still places where callbacks are better). The problem is that this is a field that has been heavily studied, and there are great solutions to this problem that also solve countless other problems, and interop well with each other. The way promises work, they solve that ONE problem but throw away the rest. If you have the choice between 2 mostly equivalent solutions to solve a problem, but one of the solutions also solve 10 other problems with essentially no drawback, why would you choose the former? This is probably already linked in this thread somewhere and is also probably was prompted someone to post this old issue to Hacker news, but this is a good explanation of the problem: https://staltz.com/promises-are-not-neutral-enough.html https://staltz.com/promises-are-not-neutral-enough.html
- todd_wanna_code 9y ago> There are still places where callbacks are better) Like? I am genuinely interested in knowing the drawbacks of promises and places where a callback like structure is more favourable. By the way, I am not contradicting you, just trying to learn.
- shados 9y agofoo.map(x => x * 2); Not sure I'd want to use a promise there :)
- imtringued 9y agoA promise can only be activated once. You still have to use callbacks for buttons and other things that can be activated more than once.
- ballenf 9y agoThe hardest part for me when I was new to Promises was that multi-layer promises would magically vanish. It was so counter-intuitive from every other programming paradigm — nested loops, deep/complex objects, and functional closures. I lost several days struggling against the concept until realizing that Promises were intended and designed to work differently than every other aspect of the language. Can you imagine the language stripping out a nested returned function and instead executing it and returning the value? That’s what Promises will do.
- draw_down 9y agoWhy does everything discussing something you personally like have to be “venom”? People here have serious, thoughtful ideas about how they could have been much nicer and why they represent a missed opportunity. Sorry but I’m just tired of every critical thought needs to be painted as overly negative and therefore worth dismissing.
- rmrfrmrf 9y agoIf you're working with Promises as glorified event handlers, then yes, it suits that use case well. The problems that arise later, though, have to do with composability, cancelation, and scheduling.