How to call an async method from a getter or setter?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
JavaScript getters and setters look like properties, but they are still synchronous language features. That means you cannot make a setter awaitable through assignment syntax, and while a getter can return a Promise, doing so usually makes the API harder to understand than using explicit async methods.
Why Getters and Setters Are a Bad Async Boundary
Property access suggests cheap, immediate work. Async code suggests delayed work, possible failure, and await. Those two mental models do not fit together cleanly.
For example, this getter is legal JavaScript because it returns a Promise, but it is easy to misuse:
This works, but store.profile looks like a value when it is really an asynchronous operation with network cost.
Prefer Explicit Async Methods
The clearer pattern is to expose async work as a method with a verb in its name.
Now the caller can see immediately that the operation is asynchronous and may need await, error handling, and retries.
Use a Getter for Cached State, Not for Fetching
One reasonable compromise is to keep the getter synchronous and have it expose cached state, while a separate async method refreshes that state.
This preserves the normal meaning of a getter. Reading the property is cheap, while the network call is explicit.
Setters Are Even More Awkward
A setter cannot be awaited through property assignment syntax. You can start asynchronous work inside a setter, but the caller cannot write await obj.value = 3 and expect meaningful sequencing.
This is valid, but it hides asynchronous side effects behind assignment. That usually makes debugging harder.
Replace Async Setters With Async Methods
If setting a value requires async work, use an async method instead of a setter.
This makes sequencing explicit and gives the caller a natural place to handle errors.
Good API Design Rule
A simple rule works well here:
- getters should expose already-available state
- setters should perform immediate synchronous state updates
- async work should live in clearly named methods
That rule makes your objects easier to read and easier to test.
Common Pitfalls
The biggest pitfall is hiding network or disk I/O behind a getter. Code that looks like ordinary property access can suddenly block on await, fail with transport errors, or trigger duplicate fetches.
Another issue is putting async work inside a setter and assuming the caller can coordinate with it. Assignment syntax does not provide a clean await point for that design.
Developers also create getters that fetch fresh data every time they are read. That can turn harmless-looking logging, rendering, or debugging code into repeated remote calls.
Finally, avoid APIs where some properties are plain values and others are promises without a naming convention. That inconsistency creates avoidable confusion.
Summary
- JavaScript getters and setters are synchronous property syntax, even when they interact with promises.
- A getter can return a
Promise, but that usually makes the API less clear. - A setter cannot be meaningfully awaited through assignment syntax.
- Prefer async methods such as
loadProfile()orsetTheme()for asynchronous work. - Use getters for cached or already-available state, not hidden I/O.

