问题描述
我正在努力找出运行长时间运行加载操作的最佳位置是使用Durandal。
I'm trying to work out where the best place to run a long-running load operation is using Durandal.
据我所知,一般建议加载数据是在ViewModel的激活
方法中,这是我通常做的事情 - 例如:
From what I can tell, the general recommendation for loading data is in the ViewModel's activate
method, which is what I usually do - something like:
viewModel.activate = function () {
var loadPromise = myService.loadData();
return $.when(loadPromise).then(function (loadedData) {
viewModel.data(data);
});
};
我知道如果我不在这里回复承诺,那么绑定通常会出现问题 - 如。
I know that if I don't return the promise here, then there's usually problems with the bindings - as this question and answer indicates.
但是,在 activate
方法中执行长时间运行的加载操作会使加载操作完成时应用程序冻结。例如,如果我的负载现在是这样的呢?
However, executing a long running load operation in the activate
method makes the app "freeze" while the load operation completes. For example, what if my load was now something like this?
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);
});
};
在这种情况下,URL会更新以反映正在加载的页面,但页面内容仍然显示上一页(我的意思是冻结)。
In this scenario, the URL is updated to reflect the page which is being loaded, but the page content still shows the previous page (which is what I mean by "freezes").
理想情况下,如果URL应该更改为新页面,并且页面内容也应显示新页面(即使尚未返回该页面的数据)。然后,当每个加载操作返回时,当数据绑定到视图模型时,页面的相关部分应该更新。
Ideally, it would be good if the URL should change to the new page, and the page content should show the new page too (even though the data for that page has not yet been returned). Then, as each load operation returns, the relevant part of the page should be updated when the data is bound into the view model.
是否有推荐的方式在Durandal中实现这个目标?
我目前的解决方案是在激活
方法,然后在 viewAttached
方法中填充数据:
My current solution is to kick-off the load in the activate
method, and then populate 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);
// Don't return the promise - let activation proceed.
};
viewModel.viewAttached = function () {
$.when(loadPromise).then(function (one, two, three) {
viewModel.one(one);
viewModel.two(two);
viewModel.three(three);
});
};
似乎可以工作,但我记得在某处依赖 viewAttached
不是一个好的解决方案。我也不确定是否有竞争条件,因为我允许激活继续进行。
It seems to work, but I remember reading somewhere that relying on viewAttached
wasn't a good solution. I'm also not sure if there is potential for a race condition since I'm allowing the activate to proceed.
还有其他建议吗?
推荐答案
你不必返回一个promise但是在这种情况下你必须在你的敲除绑定中处理这个,所以你不能绑定到未定义的元素。您可以尝试在激活中删除返回,但添加一个属性,指示模型是否仍在加载。这样的事情:
You don't have to return a promise but in that case you must handle this in you knockout bindings so you woun't bind to elements that are undefined. You can try to get rid of that 'return' in activate but add a property indicating if model is still loading. Something like this:
viewModel.isLoading = ko.observable(false);
viewModel.activate = function () {
isLoading(true);
var loadPromise = myService.loadData();
$.when(loadPromise).then(function (loadedData) {
viewModel.data(data);
isLoading(false);
});
};
然后,在您的视图中,您可以在视图仍在加载时显示一个部分加载完成后显示的一个。 Sometinhg喜欢:
And then, in your view, you can have a section that shows up when view is still loading and one that shows up when loading is done. Sometinhg like:
<div data-bind:"visible: isLoading()">Loading Data....</div>
<div data-bind:"visible: !isLoading()">Put your regular view with bindings here. Loading is done so bindings will work.</div>
这篇关于在durandal中长时间运行负载操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!