Async Getters and Setters. Is it Possible?
The other day I was refactoring some tests so I made a wrapper to access some mocked information with ease. This wrapper contained some getters and one of them retrieved a value asynchronously. Unfortunately, JavasScript syntax does not support asynchronous getters.
So. Is it not possible to have async getters? Well, it is. JavaScript lacks an async get
syntax but you can rely on several workarounds.
Just return a promise
As you should know by now:
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
So, a getter that returns a Promise is an async getter.
This works but I suppose that if you want to use async get
is to fully use the async/await syntax, not using then/catch
.
Using IIFEs
To return a Promise while using the async/await
syntax we can resort to IIFEs. A getter can return the inmediate execution of an anonymous async function, therefore a promise.
Notice the use of arrow functions. They are executed in the scope where they were defined. Meaning that this
will behave as expected.
And, what about defineProperty?
Yep. We can also use defineProperty
to deal with async getters.
Either Object.defineProperty
or Reflect.defineProperty
will work. They only differ slightly:
Object.defineProperty
returns the object or throws aTypeError
if the property has not been successfully defined.Reflect.defineProperty
, however, simply returns aBoolean
indicating whether or not the property was successfully defined.
IFFE get vs defineProperty
For the most part you can use either of them. Be aware of the difference between using get
and defineProperty
if you are dealing with classes.
When using
get
the property will be defined on the instance's prototype, while usingObject.defineProperty()
the property will be defined on the instance it is applied to.
Personally, I try to avoid classes so this subtleties do not concern me. In my case it’s a matter of personal taste. I do prefer the IIFEE get
approach by far.
Async setters
There is no async set
syntax either, but we can use the same workarounds we’ve seen to define async setters.
However, it woudn’t make much sense to do so. The assignement expression return value is discarded so you cannot await for the setter to end. Why bother?
I can think several scenarios were async getters may be useful, but it’s really hard to come with an example were an async setter makes sense. If you have one, please, leave a comment :)
Summing up
Sometimes an asynchronous getter is the best answer to a problem. Not having an async get
syntax is a shame, but we can overcome this limitation with simple workarounds. Always keep in mind the relation between promises and async functions.