Is it standard practice for my main app to be a class or an async function?

This question doesn’t really require a Playground, it’s as straightforward as this:

class App {
    \\ stuff goes here
}

new App;

Here is how a recent Babylon.js tutorial i was following builds the main structure of its app.

const runApp = async function () {
    \\ stuff goes here
}

runApp();

Here is how I see a lot of Playground examples run a Babylon.js app.

What I like about the second one is that it takes me less code to write with asynchronous functions vs. having to figure out how to even implement them in a class constructor in the first one.

Is it bad practice to use the second method going forward, or should I really figure out how to do it the first way? Thanks

1 Like

I believe that one doesn’t need to write classes every time when one needs just a function :slight_smile:

2 Likes

there are so many ways to build things , dont look at the exact syntax in an example … rather think of the logic , why it is set up like that for its expected purposes - what can you take away from that example for your own use cases etc…

The code you show is a very simplistic example , in a real world app it can be much more complicated

As mentioned the logic is what matters and yes , async and await are good tools to handle some or other order of execution.

That being said …

For myself i dont think about making constructors be async. I rather have a dedicated async “setup” function within the object to handle any async initialization requirements. I will explain why below

eg , in my configurator VUE 3 project I have a view component with this seup function :

async function setup() {
  publishSubscribe.addEventListenerGlobal(
    EventNames.MENU_INTERACTION,
    onSelect
  );
  sceneControllerCurrent = useSceneControllerFactory(route.query.roomtype);
  await sceneEntities.loadEntityList(roomFactory.entities1URL);
  await sceneEntities.loadSerializedEntities(roomFactory.serializedDataURL);
  sceneEntities.ready = true;
  sceneEntities.updateUIVIF();
  invalidateViewport();
}

it gets more complicated in real world because , this object does sometimes get destroyed , when going back to home screen to select a new room , but needs to have capabilities to perform multiple new setups when not destroyed , like loading presets or even changing the viewport object!

So there is a good reason for removing such logic from the constructor , as in this example , I call this setup function when the component is mounted ( think constructed ) but as mentioned, due to how the app works , when I load a preset , i call a dispose function and recall this setup function.

So the object itself was not destroyed in this case , and at this point I dont want to recreate it anyway , but I do want to set it up again , where it will set up differently based on new values etc…

hense why async “setup” logic is removed from object construction :wink:

here is my load preset function :

function loadPreset(presetURL) {
  invalidateComponentKey.value++;
  dispose();
  roomFactory.serializedDataURL = presetURL;
  setup();
}
4 Likes

Thanks for the answers everyone! From what I understand, it seems like it’s definitely okay to use the second method as my main application loop going forward.

But once I start making more complex projects, I should look into using more objects/classes to organize my code, and the way I would use asynchronous code in their constructors is by putting it in a separate async function and calling that, instead of attempting to put the same asynchronous code directly inside the constructor.

class Example {
    constructor {
        // DON'T put async code directly in here...
        separateFunc();
    }
}

async function separateFunc() {
    // ...put it here and call it in the constructor instead
}

Do I have that right @shaderbytes?

1 Like

yes , you got the idea perfectly :wink:

1 Like