Getter properties are a great way to mask logic and expose what appears as static values. I find it extremely elegant to differentiate functionality from attributes. This logic may hide lazy calculations to be performed only on-demand, or it may hide logic that’s based on object’s, or even application state.
For example, a User
object may have functionality like user.goOnline()
, it should have attributes like user.isOnline
. The check if a user is online should be performed on demand because this status may change from moment of instantiation to the moment of querying.
With the emerging of async/await in Javascript, it is now possible to create such lazy getters by pointing them to promises, creating more semantic APIs.
class User {
constructor(id) { ... }
goOnline() { ... }
addBadge(type) { ... }
get isOnline() {
return fetch(`/${this.username}/online`)
.then(response => response.json())
.then(data => data.isOnline)
.catch(error => { throw error; });
}
}const myUser = new User('acb33259');// Functionality
myUser.goOnline();// Attribute
if (await myUser.isOnline) { // Functionality
myUser.addBadge('online');
}
Static object can also leverage this way of typing. An API object pointing to async properties may also appear more readable.
const api = {
get request() {
return new Promise(resolve => setTimeout(() => resolve({status: 200}), 1000))
}
};(async () => {
const { status } = await api.request;
console.log(status); // 200
})();
When importing between modules — I feel the appeal is even greater.
module.exports = async () => {
const { request } = require('./api');
const { data } = await request; // Do amazing things with the data
};
And this just opens up endless sugary syntactic possibilities.
The following is a (simplified) real life example where I found using async getters made the final logic cleaner. `git tag -a ${tag} -m "${await message}"`