使用 Angular 1 应用程序在 Typescript 中管理 ES6/2015 Promise

Posted

技术标签:

【中文标题】使用 Angular 1 应用程序在 Typescript 中管理 ES6/2015 Promise【英文标题】:Managing ES6/2015 Promises in Typescript with an Angular 1 App 【发布时间】:2016-11-02 13:01:07 【问题描述】:

我们有一个使用 Typescript 构建的 Angular 1.5 应用程序,我正在尝试找出处理 ng.IPromise 与 Promise(ES6 承诺)的最佳方法。我的偏好是只处理 ES6 Promise 类型。是否有一种优雅的方式来覆盖所有 angular-js 和 angular-material(也包括在内)接口以使用 es6 承诺?

我能想到的选项:

    使用一些 d.ts 魔法来做到这一点(可以做到吗?) 到处都转换为 ES6 Promise(有效,但不直观) 为开源做贡献,分叉 ng 和 ng 材料的类型,并让它们返回 ES6 Promise 类型(我可能应该这样做,但不确定我现在是否有时间研究兔子洞)

澄清

Angular 应用程序使用的底层 Promise 实现仍然是 $q(不过,我也在应用 angular-bluebird-promises)。我只是想简化/整合所涉及的 Typescript 接口。

【问题讨论】:

$q 承诺不应盲目地被原生承诺取代,因为它们之间存在根本差异。它们是不同的东西。 $q 链可以是同步的并在摘要上运行。这不适用于其他 Promise 实现。 我仍在使用 $q 承诺(已添加说明) 那么它们应该保持两个不同的接口,因为它们引用了不同的构造函数。那有不同的……接口。您可以将它们聚合为公分母,例如IPromise,因为在 ES6/TS 应用程序中 $q 和原生 Promise 可能共存。但这几乎没有意义。在一段期望 $q 承诺的代码中意外使用本机承诺是您最不想做的事情。再说一遍,这些接口不应该混用 @estus,这是有道理的。请回答,我会接受 @Ken 我面临着同样的事情,我喜欢编写一些新代码而不将我的库硬连线到角度,所以基本上我想将 IHTTPPROmsie 返回给 Promsie,我知道 then/ catch/finally 处理程序函数在 angularjs 摘要 cicle 中运行,所以为了符合角度,我想用 $timeout 包装那些需要知道 angularjs 的部分......非常有趣! 【参考方案1】:

它们应该保留两个不同的界面是有充分理由的。

$q 承诺与其他实现之间存在根本区别。 $q 链可以同步并在摘要上运行。这不适用于其他 Promise(即原生 Promise)。

在原生和$q Promise 共存的 TS/ES6 应用程序中,Promiseng.IPromise 接口可以聚合为适合它们两者的共同点,例如IPromise(没有ng)。但这几乎没有意义。在需要 $q 承诺(反之亦然)的代码中意外使用本机承诺是您最不想做的事情,但如果使用常见的 IPromise,Typescript 不会阻止它。

如果希望从 Angular 导出承诺并由非 Angular 代码使用,最好将其转换为 Promise,正如另一个答案所建议的那样。

对于给定的非 Angular 上下文

let exportedPromise = getResolvedPromise();
...
exportedPromise.then(...);

这个

function getResolvedPromise() 
  return Promise.resolve($q.resolve());
;

将在下一次滴答时触发 then 回调。还有这个

function getResolvedPromise() 
  return $q.resolve();
;

将暂停链直到下一个根范围摘要,即使 then 已被链接到已解决的承诺上。

虽然与 TS 无关,但 this question 是一个很好的例子,说明始终了解使用的是 $q 还是原生承诺很重要。

【讨论】:

我想知道这个¿在同一个滴答声或另一个滴答声中执行代码有什么区别?只要他们两个在 angularjs 摘要 cicle 内,我不知道结果是否会有所不同。我猜你应该在示例中使用原生承诺用$timeout 包装,仅此而已,在下一个滴答声中,Angular 会消化你的更改,对吧? 竞争条件可能会有所不同,即当多段代码由于在不同的时间执行而以错误的顺序执行时。否则,如果它有效,它就会有效。在下一个tick中执行代码可能会给DOM一些时间来绘制并且对UX更好,但这需要检查。对于原生承诺,额外的超时是详尽的,可以使用 $scope.$apply() 触发摘要。 浏览器上javascript中的竞争条件...我认为这是不可能的...因为javascript中没有威胁,也许在我工作的项目中没有...我确实知道一些叫做工人,但我不知道,我从来不需要真正使用它们......不过 radraw 和 UX 是我可以想象的,因此它可能是一个小问题 竞争条件总是可能的,因为可能存在异步代码,并且与 DOM 相关的代码也可以是异步的。使用 $q 与原生 Promise 相比,您可能会受限于其他原生 Promise 引起的竞争条件,而不是 setTimeout 等,这是因为原生 Promise 在 JS 事件循环中非常快并且主要相互竞争。给定let a = 1; Promise.resolve(2).then(v => a = v)$q.resolve().then(() => console.log(a)) 将产生1Promise.resolve().then(() => console.log(a)) 将产生2 好的,你给点材料想想吧!谢谢!【参考方案2】:

是否有一种优雅的方式来覆盖所有 angular-js 和 angular-material(也包括在内)接口以使用 es6 承诺

我们只是随处使用IPromise。由于底层实现差异,很难用Promise 替换IPromise。如果你愿意,你最好做Promise.resolve(someIPromise),但它不会与角度一起玩。

【讨论】:

在 Angular 应用程序中,我正在这样做。当我们使用引用 es6 Promise Typescript 接口的外部(非特定角度)库时,事情变得不直观。

以上是关于使用 Angular 1 应用程序在 Typescript 中管理 ES6/2015 Promise的主要内容,如果未能解决你的问题,请参考以下文章

如何将 jQuery 导入 Angular2 TypeScript 项目?

Angular 2 / Typescript - 如何检查对象数组以查看属性是不是具有相同的值?

Node.js、TypeScript、JavaScript 和 Angular 之间的连接 [关闭]

将打字稿更新为v3.2.1,SDK文件夹中没有tsc.exe

vscode下搭建Typescript编译环境

如何使用 @angular/upgrade 在 Angular 1 应用程序中使用 Angular 2 组件