如何在 Node+Typescript+VSCode 中查找 Async 函数调用中缺少的 Await?
Posted
技术标签:
【中文标题】如何在 Node+Typescript+VSCode 中查找 Async 函数调用中缺少的 Await?【英文标题】:How to find missing Await on Async function calls in Node+Typescript+VSCode? 【发布时间】:2018-03-29 15:06:53 【问题描述】:我们在节点应用程序 b/c 中部署了错误,我们忘记在异步函数调用前加上“await”。
例子:
const getUsers = async () => db.query('SELECT * from Users');
const testMissingAwait = async () =>
const users = getUsers(); // <<< missing await
console.log(users.length);
;
testMissingAwait();
有没有一种简单的方法可以找到缺少 await 关键字的异步函数调用?
如果做不到这一点,编写一个自动标记这些的 Visual Studio Code 扩展需要付出多少努力? (如果有人能指出我正确的方向,我愿意解决)。
【问题讨论】:
该功能甚至需要异步吗?它有什么收获吗? (getUsers) 你在这个项目中使用打字稿吗?如果是这样,它应该在编译时捕获该错误,因为类型Promise<xxx>
没有属性“长度”。
@CRice 如果您执行“users.length”则有效,因为 Promise 没有属性“length”,但如果您忘记等待没有返回值的异步函数,那么 Typescript 将无济于事你用这个机制。有谁知道是否有一个 Typescript 设置(或其他 linter)可以检测到您没有等待的异步函数调用并将它们标记为可能的错误(您可以使用指令显式忽略仅当您想要启动异步工作时而不是等待它)?
实际上似乎有一个 tslint 规则来检测称为 no-floating-promises 的“浮动”承诺 - palantir.github.io/tslint/rules/no-floating-promises, github.com/palantir/tslint/pull/1632
ESLint 中也有这方面的东西吗? require-await
不是吗。
【参考方案1】:
TypeScript 已经这样做了
// users is a Promise<T>
const users = getUsers(); // <<< missing await
// users.length is not a property of users... then and catch are
console.log(users.length);
您可以找到不会被告知您的错误的情况 - 类型兼容的情况,例如我在这里错过了等待:
function delay(ms: number)
return new Promise<number>(function(resolve)
setTimeout(() =>
resolve(5);
, ms);
);
async function asyncAwait()
let x = await delay(1000);
console.log(x);
let y = delay(1000);
console.log(y);
return 'Done';
asyncAwait().then((result) => console.log(result));
因为console.log
不会导致我的数字和我的承诺之间出现任何类型不兼容,所以编译器无法判断我犯了错误。
这里唯一的解决方案是类型注释......但如果你要忘记等待,你很可能会忘记类型注释。
let y: number = delay(1000);
【讨论】:
【参考方案2】:TypeScript 编译器没有为此提供编译器选项。但是,TSLint 4.4 提供了检测浮动承诺的选项。您可以阅读这篇博文以获得更详细的答案:Detect missing await in typescript
下载 TSLint:
npm install -g tslint typescript
配置 TSLint:
"extends": "tslint:recommended",
"rules":
"no-floating-promises": true
运行 TSLint:
tslint --project tsconfig.json
如果您的代码中有浮动承诺,您应该会看到以下错误:
错误:F:/Samples/index.ts[12, 5]:必须正确处理承诺
【讨论】:
是的,可以,但是 VSCode 问题选项卡显示的错误比手动运行 tslint 少(例如,当您忘记问题选项卡中不存在等待时出现 tslint 错误) 我的 VS Code 也没有显示 ESLint cli 可以检测到的所有错误。安装 ESLint VS Code 插件解决了这个问题。【参考方案3】:tslint is deprecated 但typescript-eslint 对此有一个规则:no-floating-promises
此规则禁止在未适当处理其错误的情况下在语句中使用类似 Promise 的值...处理 Promise 值语句的有效方法包括
await
ing、返回以及使用两个参数或 @ 调用.then()
987654331@ 一个参数。
要使用它,您需要设置 typescript-eslint:
安装依赖项
npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
修改您的.eslintrc
文件
这些是最低要求的设置;有关更多选项,请参阅文档 (https://typescript-eslint.io/docs/linting/linting):
"parser": "@typescript-eslint/parser",
"parserOptions": "project": "./tsconfig.json" ,
"plugins": ["@typescript-eslint"],
"rules":
"@typescript-eslint/no-floating-promises": ["warn"]
(我将其设置为warn
,因为有时您可能希望调用返回Promise 的函数而不使用await
。但如果您愿意,可以将其设置为error
。)
下次运行 eslint 时,您应该会看到已应用的规则:
$ npm run lint
...
./src/database/database.ts
219:7 warning Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the `void` operator @typescript-eslint/no-floating-promises
由于您特别提到了 VS Code,这也与 ESLint plugin 很好地集成:
【讨论】:
以上是关于如何在 Node+Typescript+VSCode 中查找 Async 函数调用中缺少的 Await?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Node 和 TypeScript 获取异步堆栈跟踪?
如何在 Typescript 中获取 node_modules 包类型
如何使用 TypeScript 导入自定义 node.js 插件模块
Node.js 和 Typescript,如何动态访问导入的模块