#how to fix an async infection that has reached the constructor

18 messages · Page 1 of 1 (latest)

noble kelp
#

i recently decided to replace a low level function inside my codebase with an async version.

the issue is that since in my codebase, all functions are pretty much dependant on the previous results, i needed to make the whole parent chain of functions which call this function async

this has led to an async infection. however the issue is that at the top level i have the constructor which also needs to work synchronously, but the function it is calling is async in nature.
what should i do?
the low level function i am upgrading to is not mine and is provied my the api of the system im building on.

mystic sky
#

The general idea is that, constructor should just be used for simple initialization like assigning the properties to make the constructed instance valid, and it shouldn't do anything else beyond that.
Instead move your async logic into a factory function, which calls the async function and passes the result to the constructor.

noble kelp
#

right but in that case, my class propeties are computed using this async function

#

if i move them out of the constructor, then i get:
Property 'foo' has no initializer and is not definitely assigned in the constructor.

mystic sky
#

You pass the result into the constructor and assign it there.

noble kelp
#

could you show a small demo of what you mean?

#

sorry if im asking for too much

mystic sky
#

Instead of:

class Foo {
    prop: string

    constructor() {
        // not allowed
        this.prop = await doTheAsyncThing()
    }
}

new Foo()

Move the logic out:

class Foo {
    prop: string

    constructor(prop: string) {
        this.prop = prop
    }
}

new Foo(await doTheAsyncThing())
noble kelp
#

yess, i got this

#

wait

#

so you mean populate the prop with a place holder until foo correctly populates it?

mystic sky
#

I'm saying to move the async logic out of constructor and give that responsibility to the caller, so all the constructor does is just assigning properties and nothing else.

noble kelp
#

see thats the thing. one of my class properties is a tree object that needs to be constructed.

#

it is constructed using the async function

#

if i move that declaration outside the constructor, then the constructor thinks i havent initialized the property since its not done inside the constructor

hybrid obsidian
#

You'd build the object it and then pass it into the constructor where it's assigned to the property

#

It can be convenient to use a static function for this:

class Foo {
    thing;
    constructor(thing: "ThingType") {
         this.thing = thing;
    }
    static async create() {
        return new Foo(await doTheThing())
    }
}

You can even mark the constructor as private so Foo.create becomes the only way to make a Foo, if you want, and basically you just swap new Foo for Foo.create in your usages.

noble kelp
#

and then define all the properties inside create()?