A Promise Is a Placeholder for a Future Value

Why a promise is best understood as a container for a value you don't have yet, and why getting one back instead of handing away a callback finally starts to undo inversion of control.

September 6, 20262 min read11 / 17

Here's the actual idea this post teaches, in one sentence: a promise is a box that holds a value you don't have yet, so you can hold it, pass it around, and use it before it's actually ready.

Most explanations of promises start with .then(). That's the least interesting part. The real point is simpler: you shouldn't have to just sit and wait to think about a value that's still on its way.

A Container Around a Value You Don't Have Yet

Picture handing your coat to a theater's coat check. You don't get the coat back, you get a numbered ticket instead.

That ticket isn't your coat. It's a stand-in for it. Pocket it or hand it to a friend, all without ever touching the coat itself. Trade it in later, and you get the real thing.

A promise is that ticket, for a value instead of a coat. A thunk was already this idea: a container that doesn't care whether its value exists yet. A promise is the same container, just built into the language, with a name of its own: a future value.

Other languages had a version of this idea years before JavaScript did. What's new is that it's now built-in, so nobody has to hand-build it the way you just did with thunks.

Promises Flip Who's Actually in Control

Here's the part that matters more than any of that.

Inversion of control happens the moment you hand your callback to something else. From then on, that other code decides when your callback runs, how many times, and with what. You already know how badly that can go wrong.

A promise flips that relationship. Instead of handing away a callback and hoping, you call a function and it hands you something back, a promise, and you're the one who decides what happens next.

It's less like giving someone your phone number and hoping they call, more like signing up for a notification: you subscribe to "done," and it fires whenever the work is actually ready.

There's still a real API to look at, and real guarantees to unpack. But this one flip, keeping control instead of giving it away, is what everything else about promises is built on.