Mark.Ben Mark.Ben - 1 month ago 6
Javascript Question

How to get a property of an object whenever we are sure the object has been created

I have a variable called

MainVM
which gets set to a new instance of knockout view model whenever the corresponding
.js
file is loaded in base layout view and then in different view I need to set one of the properties of MainVM.

var MainVM;
core.load(["Scripts/Shared/MainViewModel.js"],
function () {
MainVM = new MainViewModel();
});


Issue: I need to make sure
MainVM
got set the new instance of
MainViewModel
and then set a property to it.
What I have done I wrap it inside a
setTimeout
and after 200ms I call
MainVM
with the hope that it has been set as below:

$(function() {
setTimeout(function() {
core.load(["Scripts/Account/AccountMainViewModel.js"],
function () {
MainVM.CurrentVM(new AccountMainViewModel());
MainVM.CurrentVM().Load();
});
}, 200);
});


but above approach seems not to be accurate if for any reasons loading of
MainVM
takes much more than 200ms. Also, I was thinking to use
setInterval
instead to keep calling a function that check if
MainVM
is defined every 10ms. But I was wondering if any one knows a better approach, how to handle this like for example what we can use as a callback function by using
promise
and
then. But here it is not a function that I can take advantage of
promise`. It already gets called inside the shared base layout one time and cannot put it in a function and re-call it again somewhere else.

Answer

You can use $.Deferred() to perform a task when core.load(["Scripts/Shared/MainViewModel.js"]) call completes by passing MainVM to deferred.resolve() within callback function. At .ready() handler use .then() to access the resolved promise value : MainVM

var MainVM; var deferred = $.Deferred();
core.load(["Scripts/Shared/MainViewModel.js"],
  function () {
    MainVM = new MainViewModel();
    deferred.resolve(MainView);
});

$(function() {
    deferred.promise().then(function(mainview) {
      // `view` : `MainVM`
      core.load(["Scripts/Account/AccountMainViewModel.js"],
        function () {
          mainview.CurrentVM(new AccountMainViewModel());
          mainview.CurrentVM().Load();
      });
    })
    // handle error
    .fail(function(err) {
      console.log("error loading MainVM", err)
    })    
});

function MainViewModel() {
  this.id = 123;
  this.CurrentVM = function() {
    return this.id
  };
}

var MainVM;
var deferred = $.Deferred();
var core = {
  load: function(script, callback) {
    callback(script)
  }
}
core.load(["Scripts/Shared/MainViewModel.js"],
  function() {
    // asynchronous process
    setTimeout(function() {
      MainVM = new MainViewModel();
      // resolve `MainVM`
      deferred.resolve(MainVM);
    }, 1 + Math.floor(Math.random() * 3500))
  });

$(function() {
  deferred.promise().then(function(mainview) {
      // `view` : `MainVM`
      core
        .load(["Scripts/Account/AccountMainViewModel.js"], function() {
          console.log(mainview.CurrentVM(), MainVM)
        });
    })
    .fail(function(err) {
      console.log("error loading MainVM", err)
    })
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>