2

I'm wondering if custom "thenables" (aka an object with a .then() method) are approved/documented? How do they compare to real Promises? I suppose it matters how you implement then, so I'm wondering if there's documentation with some DOs and DONTs.

This page suggests:

.then may return an arbitrary “thenable” object, and it will be treated the same way as a promise.

Can't find any docs on this.

Michael Lewis
  • 4,252
  • 6
  • 28
  • 39
  • `I suppose it matters how you implement then` indeed it does - as for documentation ... maybe the .then description in the "spec" https://promisesaplus.com/ – Jaromanda X Nov 08 '17 at 11:23
  • I'll have to study that link, thank you. I'm hoping to find some more thorough examples of how to implement your own custom thenables. – Michael Lewis Nov 08 '17 at 12:10
  • Not sure what you mean by "approved"? – Bergi Nov 08 '17 at 14:10
  • Even if a custom .then-able works in some cases, it might fail in others, if it's not a "real" promise, for example. That's why I was wondering if custom thenables were "best practice", or an intended feature. I would think that creating custom .then-ables has a lot of potential, and there would be lots of people doing it. And there would be specific patterns/anti-patterns. – Michael Lewis Nov 10 '17 at 11:05
  • @MikeLewis What potential do you see that is not covered by simply creating a "real" promise? – Bergi Nov 10 '17 at 15:23

1 Answers1

3

How do thenables compare to real Promises?

In that you don't know whether they are real promises or not. Have a look at Regarding Promises/A+ Specification, what is the difference between the terms "thenable" and "promise"?.

I'm wondering if there's documentation with some DOs and DONTs about how to implement them (as that seems to be what matters)

There's the (pretty simple) Promises/A+ specification that documents how thenables are treated. ES6 promises (and by extension, await) follow this. Basically:

  • your object has a property with the name then whose value is a function
  • the function will get called with two callbacks
  • you can call either of them - asynchronously or not
  • the first call determines what happens to the promise that assimilated your thenable

It's really no magic. You call the first argument when you want to resolve with a value, and you call the second argument when you want to reject. There are no DONTs assuming a proper promise implementation - you can call the callbacks as often as you want, and keep them around as long as you want: the calls should be ignored and the reference should not leak memory.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • That last part seems a little wonky. So I await my custom thenable, potentially in a loop or something. Potentially 1000 times per second (I don't have a real use case, just what-if-ing here), and each time, it gives me a new cb. If I'm using a typical callback pattern (array of functions), then I'm storing 1000s' of callbacks, calling *all* of them each time my streamy.thenable emits data...? – Michael Lewis Nov 10 '17 at 11:10
  • You're saying, it doesn't matter if I call those already-called callbacks again, it shouldn't hurt anything. But, in the case that there are a lot of them... doesn't seem to be a great idea. – Michael Lewis Nov 10 '17 at 11:11
  • @MikeLewis Actually an `await` in a loop will suspend the loop until the value is resolved :-) Yes, piling up callbacks is not a great idea. Of course it still hurts to do many useless operations, and to keep useless stuff in memory; all I'm saying is that it does not affect the promises that were resolved with the thenable. – Bergi Nov 10 '17 at 11:37
  • What about chaining? A custom thenable's `.then()` method should return a new thenable, with a `.then()` method, that's somehow linked to the return value of the function passed to the first one. I think? Not sure how that applies to repeatable thenables (like events/streams) – Michael Lewis Nov 10 '17 at 12:46
  • No. The return value of `then()` is discarded when it is assimilated by a promise (or `await`). Chaining only matters when you want to work with thenables yourself - but then really there's no good reason not to just use a proper promise. – Bergi Nov 10 '17 at 15:22