To promise or not to promise

1 for 1 so far on the posting every day thing.

Yesterday I ran into some pain with my code that I thought was interesting, so today I'll explain how that played out.

class Smarts {
    then(fn) {
        fn("Oh no.")
    }
    async self() {
        return this
    }
}

const smarts = new Smarts()
const result = await smarts.self()

// result -> "Oh no."

And now we have a problem. Async functions return a promise which resolves to their return value. When a promise resolves to a promise, the first promise actually keeps waiting for the second promise and resolves to the value of the second promise. And finally, since JavaScript has no types, everything with a .then looks like a promise. (I'm sure there's a Maslow's Hammer reference that I could make here.)

Instead of the async method resolving to this, it resolves to the value of whatever this.then sends to its callback. Because the class looks like a promise.

In this case, instead of .self() resolving to the same object, as one might expect from the method implementation, it resolves to "Oh no.".

The solution to this problem? Make your class not look like a promise, or everyone will treat it as one.

This stumped me for an annoyingly long time, because of course my code was not as simple as just a class with then and self methods in isolation.

Unrelated to code, the photo of the day is of Sub-Zero Scuffle, a fighting game tournament that I attended last weekend (7-8 March). The events were Smash Ultimate, Tekken 7, Samurai Shodown, Street Fighter 5, Marvel vs Capcom, Mortal Kombat 11, Soul Calibre 6, and Power Rangers: Battle for the Grid. It was a really good time.

— Cadence

← Previous: Hello blog!Next: Amanda gives health tips →