This is a common gotcha in Javascript implementations, in that you think you want this, but you really don't! Now you never know if your code is synchronous or will run in a subsequent tick. Your call tree will look completely different depending on race conditions...
This comes up in user code as well; any time you write a function that takes a callback, it's probably a good idea to either always run it either in the same call tree or in a new stack, but never mix the two. It's usually easier to just do the latter using process.nextTick.
new Promise(resolve => resolve("resolved!")).then(result => console.log(result));
console.log("next statement");
Prints "next statement" then "resolved!". Promise.resolve("resolved!").then(result => console.log(result));
console.log("next statement");Part of it is that if your API requires you to think about whether or not it will run in the current or next tick, that's probably not the right API.
I find in JavaScript it's best to just assume your callbacks could be called at any time, in any order. And if you need a specific priority then write some code that actually explicitly orchestrates that.
No, I really, really, DO want this. And I want my entire codebase written in such a way that this is fine.
You need consistent abstractions to make asynchronous logic flow comprehensible. And once you have them, stick to them rigorously. Promises are such an abstraction. Build on it, don't ruin it.
Yes, there are lots of ways to ruin it. And for every way it can be ruined, there is a way to make it work without breaking the abstraction. Do the latter.
This doesn't break the abstraction, but it does make the abstraction simpler. It means that your callbacks (or whatever abstraction is built on top of them) are always called from the same context.
Here's a good article about how callbacks get scheduled: https://jakearchibald.com/2015/tasks-microtasks-queues-and-s...
Asynchronous execution isn't an unfortunate design choice to be papered over; better to make it as easy as possible to learn and work with.
The Linux (and other OS'es) kernel handles I/O asynchronously, yet processes using open(2) + friends work quite well and are usually written in synchronous style. That the actual asyncness is hidden in kernel space does in general not lead to bad programs; and whoever needs async in the space of a single process can still use async tools provided by the kernel when needed. That tooling is much better as it leads to simpler code.
I don't see ES7's async support being there yet. Elixir, Go, a number of others: much more.
At least that's how it's always felt when I've used it for anything non-trivial yet well within its typical set of use cases.
When you chain and compose together operations on promises using a nice fluent API, you're building up a monadic value that encapsulates the whole computation. You can then apply error handling to the final monadic value and be sure all errors across the whole computation will route to a single handler. When reading and writing code, the division between "creating the computation" and "running the computation" is thereby explicit and the error handling obvious.
I've found promises most useful in managing asynchronous operations in the browser. With UI widget support (disabling things for the duration of a promise computation, showing spinners, showing progress bars, etc., automatically handling errors in an error alert area) it makes non-blocking UI much much easier to get right. For parallelism, I find different approaches easier to reason about, whether it's work queues or something like parallel LINQ / Java 8 Streams.
i am a mediocre developer and it is super hard to find resources. either they are way to beginner such as an introduction yo for loops, a project structure that is not modular but one monolithic binary for the basic example or an otherwise simplified usecase that can not really be extended very well.
otoh, some stuff is way to intense and can't grep that either. if you know of any good design patterns that explain concepts like promises, leveraging functional closures in a factory/singleton or otherwise great code concepts; but explained either at the intermediate or beginner level, that would be great.
i love resources that assume limited knowledge, they just don't seem to go into the interesting/useful parts of the language in enough depth to leverage
From what I read, it is basically the same thing.
The difference is SUPPOSED to be that a Future is read-only while a Promise is settable. And should be set at most once! So you can use a Promise as a Future, but you can't always use a Future as a Promise.
Linguistically you can understand this as, "I Promise you'll see a Future answer." I need to be able to write to the Promise to fulfill it. You can only hope that some day the Future will arrive.
on JVM: Future is read-only (public), Promise is writable (private)
The writable interface has "resolve" and "reject" to return a value. The readable interface has "then", "error", "finally" etc which let you compose and combine functions that deal in asynchronous values.
The best Javascript implementation of promises is Bluebird, which doesn't expose a Deferred instance to avoid confusion, it is very nice. bluebirdjs.com/docs/api-reference.html
You won't see that in the typical "check out how cool promises are, async and fast all the things".
And promises indeed look cool, and make for nice short demos and they are easy to understand in short examples. Only when you start building a large applications based on them, where error handling has to be done, you start realizing they are bit like threads. Promise callback chains started from one event, can interfere with other promise callback chains that started from another event. And if they modify the same data, you now also have a race condition as well.
I would basically look at this statement "In the synchronous world, it’s very simple to understand computations when thinking about functions: you put things into a function, and the function gives you something in return" and follow through, but in a different direction -- pick the synchronous world if you can.
Sequential things should be sequential and concurrent things should be concurrent. Single request processing is sequential. For this request do x,y,z in order. Can't do y unless x finished. Well sit and wait for x to finish. But requests themselves can be concurrent and run in parallel. For example a request comes in, reads the database, updates the database, bumps metrics, makess other sub-requests and then responds. It is sequential and should be kept sequential. If you platform cannot handle that, think very well about your platform, and perhaps pick a better platform. What does that mean practically? It means picking green threads (Python gevent, eventlet), it means Elixir, Erlang, Go goroutines, Rust's threads. Streams can be used as a higher level abstraction sometimes and so on.
Another good way to make things sequential is C#-style async/await, which is enough syntactic sugar over promises that everything looks sequential again.
I've always been fascinated why there is such a difference between spelling in "British" and "American" English, I remember reading that the main reason was Webster's dictionary and his desire to reform spelling according to pronunciation. That Wikipedia article though quotes John Algeo: "He was very influential in popularizing certain spellings in America, but he did not originate them."
So now I'm as confused as ever. Why DID the spellings change so significantly. I can accept that they took hold due to Webster's work, but I wonder why the differences arose in the first place?
[1] https://books.google.com/ngrams/graph?content=fulfil%2Cfulfi...
For a really interesting look ahead to how Promises (and more!) might address sync/async symmetry in ES6/7, check this out: https://youtu.be/DqMFX91ToLw
Then use async/await and look at node-modules.com to find modules that convert to promises so you can use async/await.