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传递数据。