【问题标题】:How to find missing Await on Async function calls in Node+Typescript+VSCode?如何在 Node+Typescript+VSCode 中查找 Async 函数调用中缺少的 Await?
【发布时间】: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&lt;xxx&gt; 没有属性“长度”。
  • @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 不是吗。

标签: node.js typescript async-await visual-studio-code vscode-extensions


【解决方案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 deprecatedtypescript-eslint 对此有一个规则:no-floating-promises

    此规则禁止在未适当处理其错误的情况下在语句中使用类似 Promise 的值...处理 Promise 值语句的有效方法包括 awaiting、返回以及使用两个参数或 @ 调用 .then() 987654331@ 一个参数。

    要使用它,您需要设置 typescript-eslint:

    1. 安装依赖项

      npm install --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
      
    2. 修改您的.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 很好地集成:

    【讨论】:

      猜你喜欢
      • 2017-05-29
      • 1970-01-01
      • 2017-09-10
      • 2021-01-14
      • 2020-04-13
      • 2020-09-02
      • 1970-01-01
      • 2016-02-26
      • 2020-07-20
      相关资源
      最近更新 更多