Javascript 初始化和异步加载
目前,我正在通过网格应用程序模板提供的Javascript 初始化和异步加载,javascript,windows-8,microsoft-metro,winjs,Javascript,Windows 8,Microsoft Metro,Winjs,目前,我正在通过网格应用程序模板提供的data.js异步加载数据。由于StorageFile类的异步性质,在设置全局WinJS命名空间中的数据之前,groupedItems.js(“Hub”页)在ready处理程序中调用\initializeLayout存在问题 在data.js中: fileNames.forEach(function (val, index, arr) { var uri = new Windows.Foundation.Uri('ms-appx:///data/'
data.js
异步加载数据。由于StorageFile类的异步性质,在设置全局WinJS命名空间中的数据之前,groupedItems.js
(“Hub”页)在ready
处理程序中调用\initializeLayout
存在问题
在data.js
中:
fileNames.forEach(function (val, index, arr) {
var uri = new Windows.Foundation.Uri('ms-appx:///data/' + val + '.geojson');
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function (contents) {
// ... read, parse, and organize the data ...
// Put the data into the global namespace
WinJS.Namespace.define("Data", {
items: groupedItems,
groups: groupedItems.groups,
getItemReference: getItemReference,
getItemsFromGroup: getItemsFromGroup,
resolveGroupReference: resolveGroupReference,
resolveItemReference: resolveItemReference
});
});
});
}
// ...
// This function updates the ListView with new layouts
_initializeLayout: function (listView, viewState) {
/// <param name="listView" value="WinJS.UI.ListView.prototype" />
if (viewState === appViewState.snapped) {
listView.itemDataSource = Data.groups.dataSource;
listView.groupDataSource = null;
listView.layout = new ui.ListLayout();
} else {
listView.itemDataSource = Data.items.dataSource;
listView.groupDataSource = Data.groups.dataSource;
listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
}
},
// ....
在groupedItems.js
中:
fileNames.forEach(function (val, index, arr) {
var uri = new Windows.Foundation.Uri('ms-appx:///data/' + val + '.geojson');
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(uri).then(function (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function (contents) {
// ... read, parse, and organize the data ...
// Put the data into the global namespace
WinJS.Namespace.define("Data", {
items: groupedItems,
groups: groupedItems.groups,
getItemReference: getItemReference,
getItemsFromGroup: getItemsFromGroup,
resolveGroupReference: resolveGroupReference,
resolveItemReference: resolveItemReference
});
});
});
}
// ...
// This function updates the ListView with new layouts
_initializeLayout: function (listView, viewState) {
/// <param name="listView" value="WinJS.UI.ListView.prototype" />
if (viewState === appViewState.snapped) {
listView.itemDataSource = Data.groups.dataSource;
listView.groupDataSource = null;
listView.layout = new ui.ListLayout();
} else {
listView.itemDataSource = Data.items.dataSource;
listView.groupDataSource = Data.groups.dataSource;
listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
}
},
// ....
/。。。
//此函数使用新布局更新ListView
_initializeLayout:函数(listView、viewState){
///
if(viewState===appViewState.snaped){
listView.itemDataSource=Data.groups.dataSource;
listView.groupDataSource=null;
listView.layout=新建ui.ListLayout();
}否则{
listView.itemDataSource=Data.items.dataSource;
listView.groupDataSource=Data.groups.dataSource;
listView.layout=newui.GridLayout({groupHeaderPosition:“top”});
}
},
// ....
鉴于我无法将此代码从该文件移到data.js
中Promise的done()
函数中,如何使应用程序在初始化布局之前等待在WinJS命名空间中初始化data
(加载数据和加载页面)和一个操作(初始化网格),只有在两个异步操作完成后才需要执行(加载页面,数据可用)。根据您希望采用的体系结构方法,有很多方法可以解决此问题
蛮力方法是创建一个新函数,检查文档是否已准备就绪,数据是否已加载,如果已准备就绪,则调用\u initializeLayout()
。然后在两个位置(加载文档的位置和数据可用的时间)调用该函数并且仅当这两个条件都满足时才会执行。您似乎可以通过检查全局data
项及其相关属性的存在来判断是否加载了数据
还有更复杂的解决方案在架构上更简洁。例如,在doc ready处理程序中,您可以检查数据是否可用。如果可用,您只需初始化布局。如果不可用,则安装通知,以便在数据可用时调用回调,然后您可以初始化布局。如果数据加载代码当前没有通知方案,则可以创建一个通知方案,供任何希望在加载数据时被调用的客户端使用。与第一种方法相比,这种方法的优势在于,数据加载代码不必知道任何有关网格的信息。网格必须知道数据-这很有意义,因为网格需要数据
当然,也有一些方法可以使用promise/done系统来实现这一点,尽管我个人对它还不太熟悉,因此没有提出一个使用它的好方法
您是否可以进一步扩展“创建通知”方案以执行回调函数,或者提供一些示例?在data.js
中,您可以添加一个名为notifywhendaready(fn)
的函数,该函数将回调函数作为参数。然后,当数据在data.js
中就绪时,它调用该回调函数(如果注册了)。在groupedItems中,它检查数据是否已经可用。如果不可用,它将安装回调并推迟调用\u initializeLayout()
,直到调用回调为止。这样,data.js
就不必特别了解\u initializeLayout()
或groupedItems.js
,但它仍然可以在其他模块需要时为它们提供正确的信息。我遇到的唯一问题是noficyhendataready(fn)的范围
仅限于data.js
,那么我应该如何传递回调函数参数fn?@rink.attendant.6-您必须使notifywhendaready(fn)
可从外部调用data.js
。有很多方法可以做到这一点。由于我不知道data.js
的结构,我不知道它的编写方式与什么是一致的。一个简单的全局函数(可能适用于data.js
中已经使用的一个名称空间)这对我来说是有意义的,但最好的答案是将其公开,就像data.js
中的其他函数公开一样。我会尝试将其放在后面。data.js中没有任何内容是公开的,因此使用WinJS.Namespace传递数据。