Trying to determine the most effective location for running a lengthy load operation with Durandal.
Based on my research, it seems that the recommended approach for data loading is within the ViewModel's activate
method, which is typically what I do:
viewModel.activate = function () {
var loadPromise = myService.loadData();
return $.when(loadPromise).then(function (loadedData) {
viewModel.data(data);
});
};
I understand that failing to return the promise can lead to binding issues, as discussed in this question and answer.
However, executing a time-consuming load operation in the activate
method can cause the app to become unresponsive until the operation finishes. For instance, consider the following scenario:
viewModel.activate = function () {
// All loads return a promise
var firstLoad = myService.loadFirstData();
var secondLoad = myService.loadSecondData();
var thirdLoad = myService.loadThirdDataWhichTakesAges();
return $.when(firstLoad, secondLoad, thirdLoad).then(function (one, two, three) {
viewModel.one(one);
viewModel.two(two);
viewModel.three(three);
});
};
In this case, the URL changes to reflect the new page being loaded but the content remains unchanged (leading to the "freeze" effect).
It would be ideal if the URL updated and displayed the new page while waiting for the data to return. Then, the relevant parts of the page could update as the data binds to the view model.
Is there a recommended approach for achieving this in Durandal?
My current workaround involves initiating the load in the activate
method and populating the data in the viewAttached
method:
var loadPromise;
viewModel.activate = function () {
// All loads return a promise
var firstLoad = myService.loadFirstData();
var secondLoad = myService.loadSecondData();
var thirdLoad = myService.loadThirdDataWhichTakesAges();
loadPromise = $.when(firstLoad, secondLoad, thirdLoad);
// Proceed without returning the promise.
};
viewModel.viewAttached = function () {
$.when(loadPromise).then(function (one, two, three) {
viewModel.one(one);
viewModel.two(two);
viewModel.three(three);
});
};
This solution appears to work, but I recall hearing that relying on viewAttached
may not be optimal. Additionally, there could be potential race conditions since activation continues.
Any other suggestions?