Aside from the control flow aspect, I think promises are poisoned by exceptions which are very problematic in a dynamically typed language. Here’s my blog post on the problem with try catch which gets brought along into promises, which get brought along into async/await. The only solution I’ve seen proposed for this is bounce.
Interesting read. Another solution could be to yield a promise from a generator and re-enter the generator with a list of two items. The first representing a potential error (or undefined) and the second the actual resolved value. This way we could handle errors ala Golang and avoid mixing exceptions with operational errors.
At studio we’ve been using a custom Future object for years, and when Promises were spec’ed out, I was a bit surprised (and disappointed) to see how they were built. The main good thing about them was the use of then, which makes the code easy to read. As for the rest, this article sums up some of the issues. No cancellation is quite bad, especially if you wrap network requests in promises.
I spent some time around the JS community as this was being designed, and the issues were known, people just didn’t seem to care/thought that arguments like these were some kind of purism/idealism that wasn’t useful. That was my impression at least.
I’ve had a bit of a struggle with promises for similar reasons as well. Instead of being a very general notion, promises fit really well into a specific problem, but are a bit harder outside of that.
This is mostly fine for me, because I do front-end JS. My main thing is “kick of some AJAX-y stuff and work off of that”. And async/await syntax is…. basically the ideal syntax for handling a lot of this. It works “as intended”, including for catching exceptions! Though then exceptions become your failure state, and so you mix operational errors with… business errors? Excpetions are a bit overloaded.
But if you work off things like cancellation, or stuff that’s a bit more “task-y”, it gets rough. For example “I want to send an HTTP request, and cancel any existing request for the same endpoint” (useful for things like search). There’s some missing funcitonality compared to, say, coroutines that make more complex state machines harder.
Though to be honest as a primitive promises are…. mostly fine. You can at least build the more complex stuff off of a relatively simple building block. To contrast to python3’s async model, which has just enough complexity to be hard to expand upon.
It’s really useful for APIs to be opinionated. As an API user I can expect all promises to behave similarly. If I want to build an abstraction with different opinions I can do that. After all Promises can be polyfilled so an equivalent with different opinions presumably could be too.
Wow I really learned a lot of my assumptions about promises in javascript were dead wrong.
Aside from the control flow aspect, I think promises are poisoned by exceptions which are very problematic in a dynamically typed language. Here’s my blog post on the problem with try catch which gets brought along into promises, which get brought along into async/await. The only solution I’ve seen proposed for this is bounce.
You should submit your blog post.
Interesting read. Another solution could be to yield a promise from a generator and re-enter the generator with a list of two items. The first representing a potential error (or undefined) and the second the actual resolved value. This way we could handle errors ala Golang and avoid mixing exceptions with operational errors.
At studio we’ve been using a custom Future object for years, and when Promises were spec’ed out, I was a bit surprised (and disappointed) to see how they were built. The main good thing about them was the use of
then, which makes the code easy to read. As for the rest, this article sums up some of the issues. No cancellation is quite bad, especially if you wrap network requests in promises.I spent some time around the JS community as this was being designed, and the issues were known, people just didn’t seem to care/thought that arguments like these were some kind of purism/idealism that wasn’t useful. That was my impression at least.
I’ve had a bit of a struggle with promises for similar reasons as well. Instead of being a very general notion, promises fit really well into a specific problem, but are a bit harder outside of that.
This is mostly fine for me, because I do front-end JS. My main thing is “kick of some AJAX-y stuff and work off of that”. And
async/awaitsyntax is…. basically the ideal syntax for handling a lot of this. It works “as intended”, including for catching exceptions! Though then exceptions become your failure state, and so you mix operational errors with… business errors? Excpetions are a bit overloaded.But if you work off things like cancellation, or stuff that’s a bit more “task-y”, it gets rough. For example “I want to send an HTTP request, and cancel any existing request for the same endpoint” (useful for things like search). There’s some missing funcitonality compared to, say, coroutines that make more complex state machines harder.
Though to be honest as a primitive promises are…. mostly fine. You can at least build the more complex stuff off of a relatively simple building block. To contrast to python3’s async model, which has just enough complexity to be hard to expand upon.
It’s really useful for APIs to be opinionated. As an API user I can expect all promises to behave similarly. If I want to build an abstraction with different opinions I can do that. After all Promises can be polyfilled so an equivalent with different opinions presumably could be too.