locked
Loading a file and processing it asynchronously

    Question

  •  

    In Visual Studio 11, I am building a HTML5 Metro application that reads and processes a file on initialization. I have the following code:

    var ws = Windows.Storage;

    Debug.enableFirstChanceException(true);
    var myDataSource = {};

    var id = function (elementID) {
       
    return document.getElementById(elementID);
    }

    WinJS.Namespace.define('ToDoToday', {
        id
    : id,
    });

    function initialize() {
    Windows.Storage.KnownFolders.documentsLibrary.createFileAsync("taskList.todo", Windows.Storage.CreationCollisionOption.openIfExists)

    .then(function (file) {
       
    return file.openAsync(Windows.Storage.FileAccessMode.readWrite);
    })

    .then(function (stream) {
       
    var inputStream = stream.getInputStreamAt(0);
       
    var reader = new Windows.Storage.Streams.DataReader(inputStream);

       
    var size = stream.size;
       
    if (size > 0) {
            reader
    .loadAsync(size).then(function(){
                myDataSource
    = reader.readString(size);
           
    })
       
    }
    })
    .then(function () {
       
    WinJS.Namespace.defineWithParent(ToDoToday, 'Tasks', {
            data
    : myDataSource,
       
    })
    })
    .then(function () {
       
    WinJS.UI.processAll()
    })
    .then(function () {
       
    var basicListView = WinJS.UI.getControl(document.getElementById("taskChecklist"));
        basicListView
    .dataSource = ToDoToday.Tasks.data;
        basicListView
    .refresh;
    });
    }
    document
    .addEventListener("DOMContentLoaded", initialize, false);

    The initialize function never loads the file. Because of the chained thens, the debugger doesn't return anything useful.

    The eventual error is on the databind:

    JavaScript runtime error: Object doesn't support property or method 'createListBinding'

    The binding appears to work just fine if I don't read from a file.

    I am sure my problem is a functional misunderstanding of how to chain async calls, and a second set of eyes can't hurt.


    Check out my new C# 2010 All In One for Dummies book at Amazon!
    Monday, January 02, 2012 1:30 PM

Answers

  • Hi Bill,

    Is there a compelling reason to store you file in you documents directory.  I think you would be better off storing it in the app local or roaming storage.  Here is a way you can bind a json database to a file in your local app storage and bind it to a list view:

                WinJS.UI.processAll()
                .then(function () {
    
                WinJS.Application.local.readText("json.db").then(
                function (data) {
                        var state = {};
                        try {
                            state = "done";
                            basicListView = WinJS.UI.getControl(document.getElementById("basicListView"));
                            var theDb = JSON.parse(data);
                            basicListView.dataSource = theDb
    
    
                        }
                        catch (e) { }
                    });
    
                });
    
    

    -Jeff


    Jeff Sanders (MSFT)
    • Marked as answer by Bill SempfMVP Tuesday, January 10, 2012 6:44 PM
    Monday, January 09, 2012 4:11 PM
    Moderator

All replies

  • Hi Bill,

    I got pretty confused trying to follow your logic.  Rather than me spend too much more time on this... This is how I would debug this:

    Put a BP inside each of your .then statements to see when they get executed.

    Of particular interest will be

    here: basicListView.dataSource = ToDoToday.Tasks.data;

    and here:   myDataSource = reader.readString(size);

    and here:   data: myDataSource,

     

    -Jeff


    Jeff Sanders (MSFT)
    Tuesday, January 03, 2012 4:21 PM
    Moderator
  • I can do that, but in the meantime could you tell me the best way to do it?

     

    All I want to do is, on startup:

    1. Load a file
    2. Read it into a string (the file has JSON)
    3. Bind it to the Listview

    I have tried about 20 ways to do it and none of them seem to work for me. 

    I'll reboot into Windows 8 and set the breakpoints and get back to you on that.

    Thanks for the help.

    S


    Check out my new C# 2010 All In One for Dummies book at Amazon!
    Monday, January 09, 2012 2:32 PM
  • Hi Bill,

    Is there a compelling reason to store you file in you documents directory.  I think you would be better off storing it in the app local or roaming storage.  Here is a way you can bind a json database to a file in your local app storage and bind it to a list view:

                WinJS.UI.processAll()
                .then(function () {
    
                WinJS.Application.local.readText("json.db").then(
                function (data) {
                        var state = {};
                        try {
                            state = "done";
                            basicListView = WinJS.UI.getControl(document.getElementById("basicListView"));
                            var theDb = JSON.parse(data);
                            basicListView.dataSource = theDb
    
    
                        }
                        catch (e) { }
                    });
    
                });
    
    

    -Jeff


    Jeff Sanders (MSFT)
    • Marked as answer by Bill SempfMVP Tuesday, January 10, 2012 6:44 PM
    Monday, January 09, 2012 4:11 PM
    Moderator
  • PS:

    If you wanted to do something similar to what readText does but in the documents folder... You could replace readText with something like this (readText takes a default argument that will return this if it could not open the file):

     

     

     function getDbFileAsync(fileName) {
            return Windows.Storage.KnownFolders.documentsLibrary.getFileAsync(fileName);    }
    
        function GetFileFromFolderOrDef(fileName, def) {
            /// <summary locid="35">
            /// Reads the contents of a file from the container, if the file
            /// doesn't exist, def is returned.
            /// </summary>
            /// <param name="fileName" type="String" locid="36">
            /// The file to read from
            /// </param>
            /// <param name="def" type="String" locid="37">
            /// Default value to be returned if the file failed to open
            /// </param>
            /// <returns locid="38">
            /// Promise containing the contents of the file, or def.
            /// </returns>
            
    
            function onerror() { return def; }
    
            return getDbFileAsync(fileName).
                        then(function (fileItem) {
                return fileItem.openAsync(Windows.Storage.FileAccessMode.read).
                            then(function (randomAccessStream) {
                    var reader = new Windows.Storage.Streams.DataReader(randomAccessStream.getInputStreamAt(0));
                    var size = randomAccessStream.size;
                    return reader.loadAsync(size).then(function () {
                        var fileContents = reader.readString(size);
                        return (fileContents);
                    }, onerror);
                }, onerror);
            }, onerror);
        }
        
    
    function popListView2() {
        return GetFileFromFolderOrDef("json.db", "[{\"name\":\"Denise\",\"description\":\"Secretary\",\"pay\":\"50000\"}]").then(
            function (data) {
            var state = {};
            try {
                state = "done";
                var theDb = JSON.parse(data);
    

    Again, I would suggest NOT using the documents folder however.  You would need to register your app as handling that file extension and others would have easy access to your json.db file.

     

    -Jeff

     

     


    Jeff Sanders (MSFT)
    Monday, January 09, 2012 4:57 PM
    Moderator
  • See, that is EXACTLY what I wanted to know.  There just isn't enough of a body of design knowledge out there for the average developer yet. Lots of individual samples, but no real 'this is the BEST way' kind of designs.

    Would you mind if I made a blog post about this once I get it working?

    S


    Check out my new C# 2010 All In One for Dummies book at Amazon!
    Tuesday, January 10, 2012 6:44 PM
  • Blog away my friend!

    Remember stuff in the Developer Preview is just that... a preview and not even Beta yet.  I am sure there will be more documentation as things progress.  One good source for examples other than the samples is the WinJS library.  All of those .js files included by your app internally uses these WinRT functions. 

    Documentation will get better!  Some of the build conference videos are a great resource as well.  There is SO much information out there and this is a new programming paradigm so it will take some time to learn the intricacies of Metro style app development. 

    -Jeff


    Jeff Sanders (MSFT)
    Tuesday, January 10, 2012 6:52 PM
    Moderator