This is a smart attempt to make it easier for promises to be interoperable between different libraries.
The spec uses the term thenable
in just a few places. This one is the most important (empasis mine):
The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x)
. If x is a thenable, it attempts to make promise adopt the state of x, under the assumption that x behaves at least somewhat like a promise. Otherwise, it fulfills promise with the value x.
This will make implementors do a check like:
if (typeof(x.then) === 'function') {
// adopt the state of x
} else {
// fulfill promise with value x
}
If the spec instead said "if x is a promise, then...", how would the implementor know whether x
is a promise or not? There's no practical way to make sure if x
complies with the Promise spec just by inspecting it.
An implementor (say, library FooPromises
might do something like
if (x instanceof FooPromises.Promise) {
// adopt the state of x
} else {
// fulfill promise with value x
}
and it would effectively reject any promises coming from different implementations.
Instead, by using a super-simple definition of thenable
in this condition that implementors can easily verify, it's trivial to make this check and you make it possible for implementations to play nice with each other.
For you second question, I'm not sure but my idea would be that a notation [[Resolve]](promise, x)
emphasises that it's an abstract operation. If they dropped the brackets and just said Resolve(promise, x)
, it would somehow imply that implementors should make a real function named Resolve
and expose it.
This is not needed - Resolve
is not part of the promises' interface; it's just a part of their behaviour that was important enough that it was given a name and a separate section in the docs.