What's The Point Of Promises?
kendoui.com
kendoui.com
I call shenanigans. Maybe you don't intentionally throw exceptions very often, but that's hardly the point of exceptions.
Javascript is an interpreted language. Everything is an exception. Do you ever fat-finger a function name during development? That's an exception. Ever accidentally try to use "this" when it's pointing at "window"? Exception.
Those simple, natural mistakes can be lurking anywhere. They're far easier to detect and correct when the failure is propagated backward correctly to the right callers.
Also, I guarantee you will always get exceptions in production that you didn't see in development. Browsers are different, users do things you didn't think to test. If you care about quality, you need a system in place for reporting those exceptions back to the mothership, again including meaningful traces.
So if you don't know Haskell but want to see what dpratt is talking about, I'd recommend http://book.realworldhaskell.org/read/concurrent-and-multico... . Someone who knows Scala would have to expand on Scala.
I'm a big fan of semaphores, that being said I am aware of how many people shoot themselves in the foot. It requires discipline.
Have a couple of asynchronous operation queued behind each other?
Setup a semaphore before each one. Signal when previous operation is done.
Could have different semaphores for fail and success operation even.
Just for fun, I suppose there are already better solutions out there. But none of them use signals.
- Promises don't block the caller. You don't wait, you provide a method to call on completion.
- 'Signaling' a promise (completing it) causes all callbacks to run, instead of just one.
- Promises never transition from completed to not-completed. They settle.
- Promises naturally propagate values.
Semaphores can be useful for implementing a promise, but they're not quite the same.
2) Not sure what you mean here. A semaphore has a counter. You can signal for one run and only one if you want.
3)Not sure what this means, I suppose I gotta' read up
4) Yeah, this is where semaphores get ugly.
Thanks for taking your time. Appreciate it.
As a concrete demonstrate, in ECMAScript 6, which has generators (= shallow coroutines), you'll be to do transforms like this:
function logUserName() {
var user = getUserSync();
console.log(user.name);
}
// oh no, getting a user became async!
var logUserName = Q.async(function *() {
var user = yield getUserAsync();
console.log(user.name);
});
Note that the language is still single-threaded, and `getUserAsync()` doesn't block execution.A vivid example of this is at http://taskjs.org/.
A better logUserName() would let the caller handle that either by taking a callback or returning a promise. But now you've passed the buck to the caller. And now it has to be async too, all the way up the callstack.
This is the worst thing about async code regardless of whether its callbacks or promises: going to sync to async requires you to transform all code all the way up the callstack.
And yes, you always have to keep inserting `yield` all the way up the stack; you can't "hide" the asynchronicity.
I think this is good. It's important to explicitly call out the asynchronous points of execution in your code. But at the same time, the only transformation you end up needing to do is inserting `yield`.
Also, fix the semicolons. Apparently that's a thing.
They also make me even less likely to use any code that makes use of node-fibers (such as MeteorJS).
Promises are a poor solution for people not willing to properly model their tasks.
A far better way is to actually think about what you are trying to achieve and stick with a simple sequential control flow, rather than using some sort of overwrought API hammer to bash nails into your codebase everywhere.
Don't nest inline callback functions. When you pass callbacks, pass references to object functions. Model these asynchronous flows as objects. Don't pass around uncertainty. Embrace events.
On the model comment, modularity definitely makes writing code easier, but it reduces locality of code. It makes control flow harder to understand (and thus code harder to read). Promises 'solve' that by being explicit about the callflow schematic.