【发布时间】:2013-07-30 06:02:11
【问题描述】:
我正在尝试找出运行长时间运行加载操作的最佳位置是使用 Durandal。
据我所知,加载数据的一般建议是在 ViewModel 的 activate 方法中,这是我通常做的 - 类似:
viewModel.activate = function () {
var loadPromise = myService.loadData();
return $.when(loadPromise).then(function (loadedData) {
viewModel.data(data);
});
};
我知道如果我不在这里返回承诺,那么绑定通常会出现问题 - 如this question and answer indicates。
但是,在 activate 方法中执行长时间运行的加载操作会使应用在加载操作完成时“冻结”。例如,如果我的负载现在是这样的呢?
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 会更新以反映正在加载的页面,但页面内容仍显示前一页(这就是我所说的“冻结”)。
理想情况下,最好将 URL 更改为新页面,并且页面内容也应该显示新页面(即使该页面的数据尚未返回)。然后,随着每个加载操作返回,页面的相关部分应该在数据绑定到视图模型时更新。
有没有推荐的方法在 Durandal 中实现这一点?
我目前的解决方案是在activate 方法中启动负载,然后在viewAttached 方法中填充数据:
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 并不是一个好的解决方案。我也不确定是否存在竞争条件,因为我允许激活继续进行。
还有其他建议吗?
【问题讨论】:
-
一般来说,对于我的 SPA 应用程序,我会创建一个带有“加载”文本和 gif 的透明 div。这个 div 覆盖在整个页面上,以便用户获得应用程序正在尝试做某事的反馈,但同时他们不应该能够在我的页面上单击其他内容或进行某种数据操作被导航。您可以创建一个公共服务,任何视图都可以在其导航开始之前调用该服务,并在导航结束后删除 div。
-
谢谢@Yogesh,我做了类似的事情——虽然我尽量避免完整的页面覆盖,因为它们在移动设备上表现不佳。
标签: javascript single-page-application durandal