【问题标题】:TypeScript/Eslint throwing a 'Promise returned' error on a Express Router async routeTypeScript/Eslint 在 Express Router 异步路由上抛出“Promise returned”错误
【发布时间】:2021-07-10 19:49:43
【问题描述】:

我有以下端点设置来在测试运行后重置数据库:

import { getConnection } from 'typeorm';
import express from 'express';
const router = express.Router();

const resetDatabase = async (): Promise<void> => {
  const connection = getConnection();
  await connection.dropDatabase();
  await connection.synchronize();
};

// typescript-eslint throws an error in the following route:
router.post('/reset', async (_request, response) => {
  await resetTestDatabase();
  response.status(204).end();
});

export default router;

async 以来的整个路线都带有 typescript-eslint 错误 Promise returned in function argument where a void return was expected. 下划线

该应用程序运行良好,但我不确定是否应该进行更安全的实施,或者只是忽略/禁用 Eslint。知道该代码有什么问题吗?

【问题讨论】:

  • 我把它放到 Typescript 操场上,它编译没有任何错误,所以我认为代码没有任何问题。也许如果您分享您的 linting 配置,我们可以深入了解它。
  • 实际上从头开始,我已经检查了导致这种情况的 linting 规则,我会写一个正确的答案

标签: node.js typescript eslint typeorm express-router


【解决方案1】:

您似乎正在使用no-misused-promises 规则,该规则规定您不能在需要void 的地方返回Promise&lt;void&gt;

这意味着您不能从您的 Express 处理程序返回 Promise&lt;void&gt;,因为库中 RequestHandler 的返回类型指定返回类型应为 void。我建议您通过添加一个简单的return 关键字将其更改为返回Promise&lt;Response&gt;

import { getConnection } from 'typeorm';
import express from 'express';
const router = express.Router();

const resetDatabase = async (): Promise<void> => {
  const connection = getConnection();
  await connection.dropDatabase();
  await connection.synchronize();
};

// typescript-eslint throws an error in the following route:
router.post('/reset', async (_request, response) => {
  await resetTestDatabase();
  return response.status(204).send();  // <----- return added here
});

export default router;

另一种选择是避免使用async/await

router.post('/reset', (_request, response) => {
  resetDatabase().then(() => response.status(204).send());
});

【讨论】:

  • 谢谢!第二个解决方案有效,但是将返回添加到第一个解决方案一直抛出错误,真的感觉 eslint 不喜欢那个异步。规则确实是no-misused-promises,忘记说了。知道异步等待可能发生什么吗?我实际上是在尝试摆脱 .then()s 以保持一致性 =)
  • 当您将async 添加到函数时,它会自动将返回类型设为Promise。如果您像在async 函数中所做的那样不返回任何内容,则返回类型为Promise&lt;void&gt; 而不仅仅是void。老实说,我不确定 linting 规则是否值得,所以我很想禁用它。
  • 也许您可以尝试向您的处理程序添加类型注释。喜欢async (_request, response): Promise&lt;express.Response&gt; =&gt; {
  • 陛下不喜欢。试图安抚 Typescripot 的时间只有这么多:P 我将离开 then(),再次感谢伙计!
  • 没有 then() 有没有办法解决这个问题?
【解决方案2】:

我找到了一个不涉及使用 then() 的解决方案,让您可以使用异步的抽象而不会被 eslint 诅咒,有两种解决方案 (但我更推荐第二种)

第一个解决方案:使用“内部异步”

这是在 void 中使用异步的基本方法,如下所示:

router.post('/reset', (_request, response) => {
    (async () => {
        await resetTestDatabase();
        response.status(204).end();
    })()
});

第二种解决方案(推荐):“类型重叠”

第二个选项是你将它用作异步,一如既往,但是用“as”关键字说“嘿 TypeScript,这里没什么问题,呵呵”

import { RequestHandler } from 'express'

router.post('/reset', (async (_request, response) => {
    await resetTestDatabase();
    response.status(204).end();
}) as RequestHandler);

【讨论】:

  • 这样做有什么好处?听起来 OP 会因为某些期望的行为而出现 linting 错误。与其为 linting 错误创建一个复杂的解决方法,不如禁用规则更有意义......除非我遗漏了什么。
  • 嗯,有时候禁用一些规则在你使用 eslint 时有点意思,因为如果你不想要规则,那你到底为什么要使用 eslint? ??
  • 我认为这是一个很好的问题!为什么要使用 eslint?对我来说,这是围绕代码执行某些规则,以确保代码更好。如果应用规则会使代码变得更糟,那它就不是一个好规则。
  • 公平,有道理
猜你喜欢
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-03
相关资源
最近更新 更多