La programación asíncrona en JavaScript y especialmente en Node.JS ha estado basada principalmente en callbacks. Le pasas a la función que estás llamando un callback que ejecutará cuando termine de procesar lo que tenga que hacer. Esto llevaba a una pirámide de código inmanejable. La pirámide de código hace que procesar código asíncrono con bucles, o flujo condicional acabe siendo tedioso, además de ser muy propenso a errores ya que la gestión de errores se suele hacer pasando un parámetro con un posible error y otro parámetro con un valor. function(err, value) { }. Si se lanzan excepciones que no se gestionan dentro del código, se dejan de llamar a los callbacks esperados y se rompe el flujo; con lo que hace que todo sea extremadamente frágil.

Promises/A, Q, y asíncrono lineal con generadores

Con las promesas cambiamos el flujo. De funciones de tipo function myAsyncFunction<T>(...params:any[], done: (err:Error, value:T) => void) (que tienen un callback para seguir con el flujo y devuelven void) pasamos a funciones del tipo function myAsyncFunction<T>(...params:any[]) : Promise<T> (que ya no tienen el callback y lo que hacen es devolver una Promise).
Una promise es algo similar a un Event Listener, solo que no podemos hacer un dispatch y únicamente nos podemos registrar a un evento: obtener valor y obtener un error.

interface IDeferred<T> {
    resolve(value?: T): void;
    reject(err: Error): void;
    get promise(): IPromise<T>;
}

interface IPromise<T> {
    then(onResolved: (value: T) => void, onError?: (err: Error) => void, onProgress?: () => void) : IPromise<T>;
}

Básicamente cuando queremos convertir un código funcionando con callbacks tradicionales al sistema de promesas, lo que hacemos es generar un Deferred, que contiene los métodos para continuar el flujo con un valor o con un error y devolvemos la promesa vinculada al deferred, que únicamente tiene un método then, que ejecutará los callbacks que le pasamos cuando la llamamos cuando el deferred se resuelve o se rechaza. El método then devuelve otra promesa, que se lanzará cuando se complete el then actual.
De esta forma un método delay/sleep hecho con promesas quedaría así:

function sleep(timeInMilliseconds: number) : IPromise<any> {
    var deferred = new Deferred();
    setTimeout(function() {
        deferred.resolve();
    }, timeInMilliseconds);
    return deferred.promise;
}

sleep(1000).then(function() {
     alert('1 second passed');
});

Task.js permite utilizar los generadores bidireccionales de Harmony y el funcionamiento de las promesas para hacer una programación de procesos/tareas/actores/green threads/minithreads  cooperativos/multitarea no preemptiva. Esto se consigue pausando la ejecución y mandando/”generando” desde el generador una promesa. El gestor de tareas se suscribe a la promesa, y retoma el generador cuando la promesa se resuelve o se rechaza; mandando un valor de vuelta al generador, o generando una excepción dentro del contexto del generador.