Thursday, October 25, 2012

Promisable Windows Runtime Component

The async methods in Windows Runtime component can be consumed directly by C# apps, but not by JavaScript. In order to expose async method to JavaScript world, simply wrap it using AsAsyncOperation() method:
using System;
using System.Threading.Tasks;
using Windows.Foundation;

namespace WinRTComponent
{
    public sealed class Test
    {
        public IAsyncOperation<double> TestAsync(int a, int b)
        {
            return DivideAsync(a, b).AsAsyncOperation();
        }

        private static async Task<double> DivideAsync(int a, int b)
        {
            if ( b == 0 )
                throw new InvalidOperationException("Dividing by zero!");
            await Task.Delay(1000);
            return 1.0 * a / b;
        }
    }
}
Inside WinJS project you just add reference to the runtime component, and the async method will be availale (intelliSense works as well):
    WinJS.UI.Pages.define("/pages/home/home.html", {
        ready: function (element, options) {

            var tester = new WinRTComponent.Test();
            tester.testAsync(123, 2).then(function (result) {
                console.log(result);        // result = 61.5
            });
            tester.testAsync(123, 0).then(
                function (result) {
                    console.log(result);    // not reachable 
                },
                function (error) {
                    console.log(error);     // InvalidOperationException 
                });
        }
    }
Note that the async method name automatically becomes camel case (TestAsync => testAsync). Also the exception thrown by runtime component will fall to error function handler in WinJS promise then function. The exception type is visible but the original excetion string is invisible from JavaScript side: