Monday, February 04, 2013

WinJS Unhandled Exceptions and Error Messages

In Windows 8 store app unhandled exceptions can be caught by WinJS.Application.onerror event handler. The app will terminate if such onerror handler is not defined, or the onerror handler returns false. Handling those unexpected errors to avoid app crash is considered a good practice.

The code below examines the detail error message of unhandled exceptions:

    function error1() {
        var test1 = undefefinedObejct.name;
    }

    function error2() {
        throw 'error from error2';
    }

    function error3() {
        throw new WinJS.ErrorFromName('error2', 'error from error3');
    }

    function error4() {
        WinJS.Promise.as().then(function () { throw 'error from error4'; });
    }
    
    // unhandled exception caught in application onerror event:
    WinJS.Application.onerror = function (error) {
        console.log(error);
        return true; // app terminates if false
    }
    
    function errorTest() {
        //error1.type = "error",
        //error1.detail.errorLine = 12,
        //error1.detail.errorMessage = "'undefefinedObejct' is undefined",
        //error1.detail.Url = "ms-appx://errortest.js/js/default.js',
        error1();
        
        //error2.type = "error",
        //error2.detail.errorLine = 16,
        //error2.detail.errorMessage = "error from error2",
        //error2.detail.Url = "ms-appx://errortest.js/js/default.js',
        error2();
        
        //error3.type = "error",
        //error3.detail.errorLine = 20,
        //error3.detail.errorMessage = "error2: error from error3",
        //error3.detail.Url = "ms-appx://errortest.js/js/default.js',
        error3();
        
        //error4.type = "error",
        //error4.detail.exception = "",
        //error4.detail.promise = {promise object},
        error4();
    }
We can see that the error message thrown from WinJS promise is very different from the regular JavaScript code. WinJS.Promise.timeout function has two major usage:
  • WinJS.Promise.timeout(100).then(function () {}): pause 100 milliseconds then continue the next promise function.
  • WinJS.Promise.timeout(100, anotherPromise).then(function () {}): start a timer, if anotherPromise is completed within 100 millisconds, then next promise will continue to run, otherwise an error will be thrown with a 'Canceled' message.
Following code snippet tests the WinJS.Promise.timeout function:
      function dotimeTests() {
        timeoutTest(100, 1000).done(function (data) {
            var result = data; // data = 'result from timeoutTest(100,1000)
        });
        timeoutTest(1000, 100).done(function (data) {
            var result = data; // data.name = 'Canceled', data.message = 'Canceled', data.description = 'Canceled'
        });
        timeoutExceptionTest(100, 1000).done(function (data) {
            var result = data; // data = 'error from timeoutExceptionTest(100, 1000)'
        });
        timeoutExceptionTest(1000, 100).done(function (data) {
            var result = data; // data.name = 'Canceled', data.message = 'Canceled', data.description = 'Canceled'
        });
    }

    function timeoutTest(actionTime, timeout) {
        return new WinJS.Promise(function (c, e) {
            // simulate an async call that takes actionTime
            var promiseAction = WinJS.Promise.timeout(actionTime).then(function (data) {
                return 'result from timeoutTest(' + actionTime + ',' + timeout + ')';
            });
            WinJS.Promise.timeout(timeout, promiseAction).done(function (result) {
                c(result);
            }, function (error) {
                c(error);
            });
        });
    }