Just like typical expressions are evaluated at time of assignment, promise expressions are also evaluated eagerly.
Promise values act like regular values. You can reuse regular variable values later:
var x = someExpression()
// some other method or function, later:
var y = x + 1
just like you can reuse promises later:
var x = someExpression()
// some other method or function, later:
var y = x.then(x => x + 1)
You can use regular variables multiple times. If you do that, it will not cause recomputation of the expression:
var x = someExpression()
var y = x + 1
var z = x + 2
Similarly you can use promises multiple times, and it will not cause re-execution of the operation:
var x = someExpression()
var y = x.then(x => x + 1)
var z = x.then(x => x + 2)
Just like you wouldn't expect to be able to control the evaluation time of a value, similarly you can't control the evaluation of a promise. You need to wrap both in a function if you want to evaluate them later:
var x = () => someExpression()
In sync code, to handle errors we use try-catch. We must wrap the block in try-catch before evaluating:
try {
var x = someExpression()
} catch (e) {
// ...
}
Promises have their async correspondence to try-catch:
var x = someExpression()
x.catch(e => {
});
We don't expect to be able to do this for sync value expressions:
var x = someExpression()
try {
x
} catch (e) {
}
Similarly, since promises evaluate asynchronously, its reasonable to expect that the catch handler is added at the same event loop tick, and to enforce that via throwing if such a handler is not attached by the next tick of the event loop.