Typescript async/await 和 angular $q 服务

Posted

技术标签:

【中文标题】Typescript async/await 和 angular $q 服务【英文标题】:Typescript async/await and angular $q service 【发布时间】:2016-06-08 08:12:42 【问题描述】:

新的 TypeScript 异步/等待功能使用 ES6 承诺。 AngularJS 使用 $q 服务承诺,但接口略有不同。

有什么方法可以使用带有$q 服务承诺的 TypeScript async/await 功能?

【问题讨论】:

是的。第一个问题是我必须将每一个来自 ng-service 的 promise-response 转换为使用 await 来对付它。第二个问题是由 await 表达式生成的 ES6-promises 不会启动角度摘要循环 关于这个github.com/Microsoft/TypeScript/issues/6122有一个未解决的问题 【参考方案1】:

我认为您不能直接使用它们。但是将 q promise 转换为 a++ promise 应该很容易,如下所示:

function Convert<T>(qPromise): Promise<T> 

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

【讨论】:

问题在于,在这种情况下,我必须包装每个返回 $q 承诺的 ng 服务。此外,ES6 承诺不会启动角度摘要循环。所以,在这种情况下,我必须在每个 await 之后调用 $apply【参考方案2】:

最后我使用了以下解决方法:

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);
    ;
]);

Compliper for Typescript 1.8 在每个使用await 运算符的文件中生成__awaiter 函数。我将其替换为传递自定义Promise 构造函数的实现,该构造函数在每次resolvereject 调用后启动摘要循环。这是使用示例:https://github.com/llRandom/ts-awaiter

【讨论】:

只是出于好奇,这个句柄是如何拒绝的?捕获块? 是的。在存储库中添加了一个示例 这可能会导致不需要的摘要,而摘要是 AngularJS 应用程序性能最常见的瓶颈。并且该解决方案不适用于 TypeScript ES2017 目标...原生 async/await 已经存在。【参考方案3】:

你可以让它像这样工作:

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

【讨论】:

谢谢,比我的版本简洁多了。不知道 $q 服务可以用作兼容 es6-promises 的构造函数 这行得通,我现在在几个项目中使用它。但我不禁动摇了这种调皮的感觉。用 Angular 的 $q 服务替换全局 Promise 对象似乎......hackish。 用 $q 替换原生 Promise 可能是对应用程序所能做的最糟糕的事情。它们是根本不同的实现,行为不同,这将破坏所有依赖于Promise 的第三方代码。关于“hackish”$window 的说法是错误的——它的存在不是因为 Angular 无法使用原生窗口,而是因为 DI 很好。 @estus 那么我们应该怎么做呢?我一直在网上寻找 async / await 与 AngularJS 正常工作,但我找不到一个好的共识。 @Schoof 顺便说一句,答案对原生 async(TypeScript es2017 目标)无论如何都不起作用,因为它依赖于内部原生实现而不是 Promise 全局。例如见***.com/a/45119519/3731501。应在异步函数执行后以或多或少明确的方式触发摘要。

以上是关于Typescript async/await 和 angular $q 服务的主要内容,如果未能解决你的问题,请参考以下文章

Gulp/Typescript/Async/Await 代码不起作用 - 为啥?

为啥 Typescript 认为 async/await 返回包装在承诺中的值?

实现一个 async/await (typescript 版)

TypeScript 2.1 async/await ES5 __awaiter 和 __generator 为每个 ts 文件生成

typescript 使用async / await测试NgRx Facade。

Typescript async/await 无法确定正确的返回类型