Typescript async/await and angular $q service

All we need is an easy explanation of the problem, so here it is.

New TypeScript async/await feature uses ES6 promises. AngularJS uses $q service promises with slightly different interface.

Is there any way to use TypeScript async/await feature with $q service promises?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

You can make it work like this:

angular.module('your app')
        .run(['$window', '$q', function($window, $q) {
            $window.Promise = $q;
        }]);

Method 2

I do not think you will be able to use them directly. But it should be quite easy to convert q promise into a++ promise, something like this:

function Convert<T>(qPromise): Promise<T> 
{
    return new Promise<T>((resolve, reject) =>
    {
        qPromise.then((result: T) => resolve(result), (e) => reject(e));
    });
};

Method 3

Finally I used the following workaround:

declare var __awaiter: Function;
(window as any).__awaiter = __awaiter; // set global __awaiter to avoid declaring default __awaiter in other files
async () => { } // dummy async function to generate __awaiter code for current file

angular.module('ts-awaiter', []).run(['$timeout', ($timeout: ng.ITimeoutService) => {
    function wrap(func: Function) {
        return function () {
            func.apply(this, arguments);
            $timeout(() => { }); // run angular digest
        };
    }

    var oldAwaiter = __awaiter;
    (window as any).__awaiter = (thisArg: any, _arguments: any, P: Function, generator: any) => {
        P = function (executor: Function) {
            return new Promise<any>((resolve, reject) => {
                resolve = wrap(resolve);
                reject = wrap(reject);
                executor(resolve, reject);
            });
        };
        return oldAwaiter(thisArg, _arguments, P, generator);
    };
}]);

Comliper for Typescript 1.8 generates __awaiter function in every file where await operator is used. I replace it with implementation which passes custom Promise constructor which initiates digest cycle after every resolve and reject call. Here is usage example: https://github.com/llRandom/ts-awaiter

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply