使用WinJS从文件读取返回值以在页面中使用

时间:2012-08-14 13:50:50

标签: windows-8 windows-runtime winjs winrt-async

我目前在Windows 8 / WinRT应用程序中读取文件时遇到问题。我有一个简单的导航样式应用程序,几个页面可以访问相同的数据,我有一个data.js文件,定义了一个具有多个成员的命名空间(数据)。应用程序的一部分将项目保存到存储在应用程序本地数据文件夹中的txt文件中。但在其他一些页面上,我需要阅读此内容或检查以前保存的项目列表中是否存在项目。为此,我在data.js文件中添加了另一个方法。问题是,当我调用此方法来检查项目是否存在时,由于异步性质,它不会立即返回值,但页面特定的js文件中的其余代码似乎仍然在它之前执行跳回到解析。这意味着检查项目的逻辑似乎不起作用。我有一种感觉,这取决于我使用.done还是.then,但我的代码如下:

  DATA.JS
   var doesItemExist= function(item_id){

    var appFolder = Windows.Storage.ApplicationData.current.localFolder;
   //note I've tried this with and without the first "return" statement
   return  appFolder.getFileAsync(dataFile).then(function (file) {
        Windows.Storage.FileIO.readTextAsync(file).done(function (text) {
            try {
                var json = JSON.parse(text);
                if (json) {
                    for (var i = 0; i < json.items.length; i++) {
                        var temp_item = json.items[i];
                        if (temp_item.id === item_id) {
                            return true;
                            break;
                        }
                    }
                } else {
                    return false;
                }
            } catch (e) {
                return false;
                console.log(e);
            }
        }, function (e) { return false;console.log(e); });
    }, function (e) { // error handling
        return false;
        console.log(e);

    });
}
 WinJS.Namespace.define("Data", {
    doesItemExist: doesItemExist
}); //all of the above is wrapped in a self executing function

然后在Page.js上我有以下内容:

    var add = document.getElementById('add');
        if (Data.doesItemExist(selected_item.id)) {
            add.style.display = 'block';
        } else {
            add.style.display = 'none';
        }

此处的所有变量都已分配,并且调试不会产生任何错误,控制只会在它到达getFileAsync之后但在它甚至经过for循环之前返回到if / else语句。但随后它会进入for循环,但在if语句完成之后。我猜这是由于它的异步性质,但我不知道如何解决它。有什么想法吗?

感谢

1 个答案:

答案 0 :(得分:3)

承诺应该在这里工作。

我创建了一个新的导航应用程序,并添加了一个包含以下代码的Data.js文件:

(function () {
    var appData = Windows.Storage.ApplicationData;

    function doesItemExist(item_id) {
        return new WinJS.Promise(
            function (completed, error, progress) {
                var exists = false;
                appData.current.localFolder.createFileAsync("data.txt", Windows.Storage.CreationCollisionOption.openIfExists).then(
                    function (file) {
                        Windows.Storage.FileIO.readTextAsync(file).then(
                            function (fileContents) {
                                if (fileContents) {
                                    if (fileContents = "foo!") {
                                        completed(true);
                                    }
                                    else {
                                        completed(false);
                                    }
                                }
                                else {
                                    completed(false);
                                }
                            }
                        );
                    },
                    function (e) {
                        error(e);
                    }
                );
            }
        );
    }

    WinJS.Namespace.define("Data", {
        doesItemExist: doesItemExist
    });
})();

请注意,我已经简化了检索和解析文件的代码,因为这与问题并不相关。重要的是,一旦您确定该项目是否存在,您可以调用已完成(存在),这会触发您返回的承诺的.then或.done。请注意,如果发生异常,您将调用错误(e),因为我在调用createFileAsync时遇到异常(当我想成为调用时,我会使用此调用而不是getFileAsync)如果文件不存在,可以创建一个文件,如果是,则使用openIfExists选项返回现有文件。

然后,在Home.js中,我将以下代码添加到就绪处理程序中:

var itemExists;

var itemExistsPromise = Data.doesItemExist(42);
itemExistsPromise = itemExistsPromise.then(function (exists) {
    itemExists = exists;
    var content = document.getElementById("content");
    content.innerText = "ItemExists is " + itemExists;
});

itemExistsPromise.done(function () {
    var a = 42;
});

var b = 0;

上面的代码将变量itemExistsPromise设置为Data.js中函数返回的promise,然后在Promise的.then函数中使用匿名函数将变量itemExists设置为从doesItemExist Promise返回的布尔值,并从Home.html中获取<p>标记(我添加了一个id,以便我可以从代码中获取它)并设置其文本以指示该项是否存在)。因为我调用.then而不是.done,所以调用返回另一个promise,它将传递给itemExistsPromise变量。

接下来,我调用itemExistsPromise.done来完成任何必须等到上面的.then中执行的工作之后的工作。

如果你在行上设置一个断点&#34; var a = 42&#34;和&#34; var b = 0&#34; (仅用于设置断点)以及行#34; itemExists = exists&#34;,您应该会发现这可以为您提供执行各个部分时所需的控件。

希望有所帮助!