Skip to content
Salatiel Queiroz
DibbbleLinkedIn

How to create a ES6 class with async constructor

Javascript, Typescript1 min read

It's not possible to create an async constructor at the moment. So, if you are searching for something like that is probably because you have to retreive data asynchronously before using any of the class methods and don't want to write multiple times the same code.

I'll show how you can acomplish that:

async-es6-class.ts
1class AsyncClassConstructor {
2 constructor() {
3 this.futureData = undefined;
4
5 this.isReady = (async () => {
6 if (!this.futureData) {
7 const futureData = await AsyncClassConstructor.doSomethingAsync();
8
9 this.futureData = futureData
10
11 return true;
12 }
13
14 return false;
15 })();
16 }
17
18 static async doSomethingAsync() {
19 return new Promise((resolve, reject) => {
20 setTimeout(() => { resolve('foo') }, 300)
21 })
22 }
23}
24
25const asyncConstructor = new AsyncClassConstructor()
26
27console.log(asyncConstructor.futureData) // undefined
28
29await asyncConstructor.isReady
30
31console.log(asyncConstructor.futureData) // foo

Explaining

isReady

You can acomplish this behavior by creating a isReady prop to you class and assigning it to an async IIFE (Immediately Invoked Function Expression). The function assinged to isReady will be responsable to call the asynchronous function and return the data you want.

doSomethingAsync

The doSomethingAsync is an async static method (but can be just an async function) that means you can call it without initiation a new class instance therefore you to use it inside the constructor to get the future data.

Real world application

Let's think of a to-do list app where you want to get the user session before retreiving the user's to-do list.

The service responsable to return the user to-do list:

todo-service.js
1import axios from 'axios'
2
3import { getUserSession } from '../somewhere'
4
5class TodoService {
6 constructor() {
7 this.userSession = undefined;
8
9 this.hasUserSession = (async () => {
10 if (!this.userSession) {
11 const userSession = await getUserSession();
12
13 this.userSession = userSession
14
15 return true;
16 }
17
18 return false;
19 })();
20 }
21
22 list() {
23 return axios.get(`/todo/list?user=${this.userSession}`)
24 }
25}

The React component that will render the to-do list:

I'm using React because is the web framework that I'm more confortable with but it could be any other

TodoList.jsx
1import { React } from 'react'
2
3import { TodoService } from '../todo-service'
4
5export const TodoList = () => {
6 const [todoList, setTodoList] = useState([])
7
8 const getTodoList = async () => {
9 const service = new TodoService()
10 await service.hasUserSession
11
12 const { data } = service.list()
13
14 setTodoList(data)
15 }
16
17 useEffect(() => {
18 getTodoList()
19 }, [])
20
21 return (
22 <ul>
23 {todoList.map(todo => <li key={todo.id}>{todo.title}</li>)}
24 </ul>
25 )
26}
© 2024 by Salatiel Queiroz. All rights reserved.
Theme by LekoArts