dinsdag, september 22, 2015

TypeScript async/await example for the browser

With the release of TypeScript 1.6 it is now possible to start using the async and await operators in your TypeScript code! You will need to enable this experimental feature, and you will need to target ES6, as TypeScript 1.6 is currently only emitting ES6 generator / yield code for your async / await code. Then when you apply for example Babel to take your JavaScript ES6 code to ES5 code, it suddenly became possible to run your async / await enabled TypeScript code in the browser!

I have compiled a working sample project to show you the application. See the following GitHub repository: https://github.com/cveld/AsyncAwait-TypeScript-Example

The following components have been used:

  • Visual Studio 2015; not required, but you get perfect syntax highlighting;
  • ASP.NET 5 beta7 web project template;
  • TypeScript 1.6; starting from version 1.6 it supports the experimental async and await operators. You will need to set ES6 as the target. TypeScript 1.6 does not support transpiling into ES5 of await/async yet, but transpiles into ES6 generator / yield code;
  • Babel; a JavaScript transpiler;
  • Gulp; a stream based JavaScript task runner;
  • Babel Browser Polyfill; included in Babel; a JavaScript file that polyfills the Promise and regenerator objects (and more).
The TypeScript example:
function test() {
    console.log("awaiter to be called...");
    awaiter();    
}

async function awaiter() {
    var result = await asyncfunc();
    console.log(result);
}

function asyncfunc() {

    var p = new Promise<string>((resolve, reject) => {
        setTimeout(() => {
            resolve('a string');
            console.log("resolved");
        }, 2000);
    });

    return p;
}
The Gulp task that is responsible for processing the .ts-file towards an ES5-compabile .js-file:
gulp.task("compile:typescript", function () {
  var tsResult =
    gulp.src(["./**/**.ts", "!node_modules/**/**.ts"])
        .pipe(sourcemaps.init())
        .pipe(tsc(tsProject));

    tsResult.js
            .pipe(babel())            
            .pipe(ngAnnotate())
            .pipe(concat("app.js"))
            .pipe(sourcemaps.write("."))
    .pipe(gulp.dest("./wwwroot/js"));
    return;
});
And the gulp task that copies over the Babel Browser Polyfill .js:
var polyfill = './node_modules/gulp-babel/node_modules/babel-core/browser-polyfill.js';
gulp.task("copy:browser-polyfill", function() {
    gulp.src(polyfill).pipe(gulp.dest("./wwwroot/lib/babel"))
});
The modified tsconfig.json:
{
  "compilerOptions": {
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": false,
    "target": "es6",
    "experimentalAsyncFunctions": true,
    "jsx": "react"
  },
  "exclude": [
    "node_modules",
    "wwwroot"
  ]
}

Geen opmerkingen: