harry
harry

Reputation: 1

Is there a way to asynchronous initialize a Viewmodel (KnockoutJS)

I want to asynchronous initialize a ViewModel. I don't mean asynchronous load the ViewModel, that I have managed (see the code below).

The ViewModel will be loaded asynchronously one time. After that, I want to do some asynchronous operations based on the parameters provided to the ViewModel. It looks like after you get the params, you must return the ViewModel synchronous, with no support for a promise/callback system. See the code below:


const defaultLoader: KnockoutComponentTypes.Loader = {
  loadViewModel: function (name, templateConfig, callback) {

    //if there is a 'fromUrl' property
    if (templateConfig.fromUrl) {

      //use import to load the code 
      import(templateConfig.fromUrl)
        .then(module => {

          //viewmodel is loaded asynchronous (one time!)
          callback( (params, componentInfo) => {
            
            //initialize the viewModel
            const model = module.default(
              params,
              componentInfo)
          
              //I can only return synchronously here:
            return model
          });
        })
    } 
  }
}

What I wanted to do is something like using async/await to signal that it has to wait before everything resolves:

          //ViewModel is loaded asynchronous (one time!)
          callback(async (params, componentInfo) => {

            //initialize the viewModel
            const model = module.default(
              params,
              componentInfo)

            //I can only return synchronously here:
            return await model
          });

But then my ViewModel ends up being the promise-object. Any suggestions on how to achieve this?

Upvotes: 0

Views: 228

Answers (1)

Brother Woodrow
Brother Woodrow

Reputation: 6372

You can't return anything from an asynchronous function, but that has nothing to do with Knockout really. You can either return a promise, or call some other function in your async function.

To that end, you should be able to use KO's default loader (don't overwrite it, like you seem to be doing now) to create the viewmodel once you've finished your processing, like so:

const customLoader: KnockoutComponentTypes.Loader = {
    loadViewModel: function(name, templateConfig, callback) {

        //if there is a 'fromUrl' property
        if (templateConfig.fromUrl) {

            //use import to load the code 
            import(templateConfig.fromUrl)
                .then(module => {

                    //viewmodel is loaded asynchronous (one time!)
                    callback((params, componentInfo) => {

                        //initialize the viewModel
                        const model = module.default(
                            params,
                            componentInfo)

                        ko.components.defaultLoader.loadViewModel(name, model, callback);
                    });
                })
        }
    }
}

Upvotes: 0

Related Questions