检测悬空承诺的静态/动态方法

the*_*nia 6 javascript node.js promise

我知道这个问题已经被处理 很多次了,但它们似乎都没有解决可靠地检测悬空承诺的问题(即使是那些正确解决的承诺)。

所以我希望能够找到一种方法(无论是在运行时还是在静态时更好)来根除“悬而未决的承诺”,尤其是此类:

async function a() {
    ... do some async operation ...
}
async function b() {
    a(); // forgot to call await on it
}
Run Code Online (Sandbox Code Playgroud)

我不小心忘记等待一个函数,并且某些异步执行的任务没有等待。通常,这些类型的错误不会引发异常,因此我不能只使用“unhandledRejection”并就此结束。

此时,经过多次绝望的尝试,我只需要一种方法来在(最佳)静态/编译/lint 时间或运行时检测这种错误模式。对我来说,运行时我认为假设我有良好的测试覆盖率应该可以工作。

tl;dr 基本上,我正在寻找一些可以执行以下操作的代码:

Error: Potential dangling promise detected!
    ...
    at b (/dangling.js:5:3)
Run Code Online (Sandbox Code Playgroud)

对于每一个悬而未决的承诺

我的思考过程

我首先尝试寻找一些静态分析库来帮助检测这些东西(理论上它应该是可能的,但我没有找到这样的东西)。不久前,我记得在 stackoverflow 的深处找到了一些东西,其中谈到使用一些打字稿检查器来检查悬空的承诺,尽管现在我再也找不到它了:(。尽管当时将整个代码库更改为打字稿是不行的-go.(后来我了解到你实际上可以使用 tsc 来检查 javascript (假设你在注释中做了一些类型注释))

目前我之前使用的是node版本11,所以我考虑使用node.js的async_hooks API并尝试监听事件(显然简单地猴子修补Promise构造函数是行不通的,因为node.js在创建Promise时绕过了Promise构造函数从异步函数返回的对象)。使用 Node v11,经过一些代码黑客攻击后,它似乎可以工作(虽然它不是很有效,因为它在 v8 引擎中丢弃了很多承诺优化,但它确实完成了工作)。整个操作中出现了一个小问题,因为我仍然必须对 Promise API 的 then/catch/finally 函数进行猴子修补,以检查我们当前是否正在调用该函数(以某种方式可以检测一些悬空的 Promise)。

现在输入节点 v12(显然我需要这个来处理某些其他正在破坏的事情),现在黑客(毫不奇怪)完全破坏了。在仔细检查版本差异后,似乎他们优化了等待/异步实现。缩小原因后,await 似乎不再调用thenPromise 的函数,而是直接执行一些本机恶作剧(不知道到底是什么)。

现在我实际上有点渴望某种解决方案(也许如果 Typescript 有某种方式对这些悬而未决的承诺进行类型检查,那么启用此检查的选项是什么?我知道(经过测试)tsc 默认情况下不会这样做) 。