Search code examples
javascriptwindows-store-appspromisewinjs

Conditional promises in WinJS


I've got two pieces of code which may or may not run when my app starts. Both produce a messageDialog, so the second must wait on the first. I'm trying to use promises to do this but I'm having issues with the returned value. Can someone point me in the right direction?

WinJS.Promise.as()
   .then(function () {
       // readTempFile returns a promise, see code below
       if (localSettings.values["lastContent"] != 0) {
            return readTempFile();
       }else{
            // what am I supposed to return here? false? 
       }
   })
   .then(function () {
       // check for release notes
       if (localSettings.values["release"] == null) {
            var updates = "Updates in this version";
            var msg = new Windows.UI.Popups.MessageDialog(updates, "Updates");
            msg.commands.append(new Windows.UI.Popups.UICommand("OK", null, 0));
            msg.showAsync();
       }
   });

function readTempFile(){
    return new WinJS.Promise(function (complete, error, progress) {
        // is my try / catch block redundant here? 
        try {
            tempFolder.getFileAsync("tempFile.txt")
                .then(function (file) {
                    file.openReadAsync().done(function (stream) {
                         // do stuff with the file
                    });
                    var msg = new Windows.UI.Popups.MessageDialog("unsaved work", "Warning");
                    msg.commands.append(new Windows.UI.Popups.UICommand("OK", null, 0));
                    msg.showAsync();
                    complete();
                }, function () {
                    // file not found
                    error();
                });
        }
        catch (e) {
            logError(e);
            error();
        }
    });
}

If both conditions are true, I get an access denied error. As I understand it, readTempFile() returns a promise object which my first then() statement should accept. But I'm not returning anything if the first conditional is met. I don't think that matters in this case as it just falls through to the next then, but it's not good programming.

EDIT:

Amended the readTempFile function to show that it produces a MessageDialog.


Solution

  • Found the answer. Inside the readTempFile function, I needed to add a done() to the showAsync() of my messageDialog, and put the complete() call in there. Otherwise, complete() was returning the promise while the dialog was still up.

    function readTempFile(){
        return new WinJS.Promise(function (complete, error, progress) {
            // is my try / catch block redundant here? 
            try {
                tempFolder.getFileAsync("tempFile.txt")
                    .then(function (file) {
                        file.openReadAsync().done(function (stream) {
                             // do stuff with the file
                        });
                        var msg = new Windows.UI.Popups.MessageDialog("unsaved work", "Warning");
                        msg.commands.append(new Windows.UI.Popups.UICommand("OK", null, 0));
                        msg.showAsync().done(function(){
                            // must be inside done(), or it will return prematurely
                            complete();
                        });
                    }, function () {
                        // file not found
                        error();
                        // have to add a complete in here too, or the app will 
                        // hang when there's no file                        
                        complete();
                    });
            }
            catch (e) {
                logError(e);
                error();
            }
        });
    }
    

    After a couple of experiments, I figured that out myself.

    As to what needed to return in my empty else statement, it was another WinJS.Promise.as()

    WinJS.Promise.as()
       .then(function () {
           // readTempFile returns a promise, see code below
           if (localSettings.values["lastContent"] != 0) {
                return readTempFile();
           }else{
                return WinJS.Promise.as()
           }
       })
       .then(function () {
           // check for release notes
           if (localSettings.values["release"] == null) {
                var updates = "Updates in this version";
                var msg = new Windows.UI.Popups.MessageDialog(updates, "Updates");
                msg.commands.append(new Windows.UI.Popups.UICommand("OK", null, 0));
                msg.showAsync();
           }
       });
    

    I found the answer in a Google Books preview of Beginning Windows Store Application Development – HTML and JavaScript Edition By Scott Isaacs, Kyle Burns in which they showed an otherwise empty else statement returning a WinJS.Promise.as()