36

I am checking out the "Promises/A+" Specification, but could not understand the following things:

On Section 1. Terminology,

1.1. "promise” is an object or function with a then method whose behavior conforms to this specification.

1.2. “thenable” is an object or function that defines a then method.

So What is the difference between the terms "thenable" and "promise"?

Also in Section 2.3. The Promise Resolution Procedure,

The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x).

So my question is:

Why is it denoted within 2 opening and closing brackets? Is there any convention?

Thank you very much.

Microtribute
  • 962
  • 10
  • 24

2 Answers2

33

So What is the difference between the terms "thenable" and "promise"?

I think the section you've already cited does answer this very well:

  • A thenable is an object with a then method. Any object.
  • A promise is an object with a then method (i.e. a thenable) that conforms to the specification.

So far so simple. I think your actual question is: "Why are they distinguished?"

The problem is that by looking at an object you cannot decide whether it is a promise.
You might be able to tell that it is a promise because you can see that its then method is implemented by yourself or someone you trust - the promise library of your choice usually. You would be able to "see" that because the object does inherit from your promise prototype, or you can even compare the method being (referentially) identical to the function you've defined. Or any other inspection method that is sufficient for you.
You might be able to tell that it is not a promise because it has no then method.
But what do you do with an object that implements then, but is not known to be a promise? It's a thenable, and will be handled as such.

The Promises/A+ specification aims for interoperability between promise implementations, and uses the existence of a .then() method for duck typing. It does specify an exact algorithm on how to treat such thenables (that might be promises or at least have similar behaviour) so that you can create an actual, trusted ("known") promise from them.

Why is it denoted within 2 opening and closing brackets? Is there any convention?

Yes, the ECMAScript specifications use this syntax for internal methods and properties:

The names of internal properties are enclosed in double square brackets [[ ]].

Those properties do not actually need to exist, they're purely used to describe what should happen - an implementation must act as if it used them. They are totally abstract operations though.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 2
    Very nice answer. It might be nice to show examples from the spec of just how untrusted a thenable is - the spec guards against getters, thenables that throw, thenables that assimilate thenables that throw and so on. – Benjamin Gruenbaum Apr 03 '15 at 19:05
  • I didn't find from Promise A+ specs what are requirements of the `then` method of thenable. If it is obligatory to return promise from it etc. specification is a bit unclear about it. – Mikael Lepistö Mar 11 '17 at 12:23
  • @MikaelLepistö The Promises/A+ specification does not assume *anything* about thenables (their `then` methods are called with two callbacks and are expected to call at least one of them back at least once) it only states the requirements for the `then` method of promises. – Bergi Mar 11 '17 at 19:06
  • Are there known issues regarding an object that has then method but is not intended to be used as promise? – rosshjb Aug 12 '19 at 05:39
  • 1
    @jinbeomhong Yes, it has happened a few times, e.g. [here](https://stackoverflow.com/q/40716155/1048572) or [there](https://github.com/visionmedia/superagent/issues/722) or [with module exports](https://github.com/tc39/proposal-dynamic-import/issues/47). However, in general people have learned quickly not to use custom `then` methods any more. – Bergi Aug 12 '19 at 11:54
7

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.

Kos
  • 70,399
  • 25
  • 169
  • 233
  • so what's the difference between thenable and promise? how would you define the difference? – Microtribute Apr 03 '15 at 15:55
  • 1
    If I make an object `var foo = {'then': function() { alert(123) }};`, then it's a thenable but obviously not a promise. – Kos Apr 03 '15 at 15:56
  • Thank you for your clarification. so a thenable is whatever has a "then" function and a promise is a special kind of thenable which conforms the specification as far as I understand. – Microtribute Apr 03 '15 at 16:09
  • Also do you know by any means why 2 brackets are used to denote a promise resolution procedure? do they denote a function or a callback? what conventions does it follow? Thank you. – Microtribute Apr 03 '15 at 16:11
  • They denote a part of the specification, not anything Javascript-specific. The brackets are there so that `Resolve` doesn't resemble a function or callback. – Kos Apr 03 '15 at 16:20
  • You say 'If the spec instead said "if x is a promise, then...", [there would be a problem]'. But the spec currently *does* say that! A bit further down: "If x is a promise, adopt its state"... and yes, this is a problem, exactly as you said. "promise" is a horrible word to be using in this context; it makes this part of the spec unclear. It's not just that the implementation has some latitude (which would be fine)-- it's that it's unclear *how much* latitudude the implementation actually has. – Don Hatch Oct 27 '16 at 00:09