使用 forEach 和 async/await,对于 Node 和 Jest 的行为不同

2024-03-31

我有一个将数据写入 mongodb 的函数,如下所示:

const writeToDB = async (db, data) => {
  const dataKeys = Object.keys(data)
  dataKeys.forEach(async key => db.collection(key).insertMany(data[key]))
}

如果我在节点脚本中运行它,效果很好。但是当我尝试在 Jest 中使用它时beforeAll我从 Jest 收到这个异步错误:

测试运行完成后,Jest 一秒钟都没有退出。这 通常意味着存在未发生的异步操作 在你的测试中停止了。

经过一些故障排除后我发现forEach造成了麻烦。使用for循环解决了这个问题:

const writeToDB = async (db, data) => {
  const dataKeys = Object.keys(data)
  for (const key of dataKeys) {
    await db.collection(key).insertMany(data[key])
  }
}

搜索这个问题时我发现了这篇文章:https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404 https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404

那里的解释很有道理,但它给我留下了一些疑问:

  • 根据这篇文章,即使在节点中它也不应该起作用 脚本。怎么就这样了?
  • 为什么在 Node 中执行它与在 Jest 中运行它不同?

edit

读完所有评论后,我意识到我的第一个问题有点无稽之谈。通常我将异步函数的结果分配给变量,如果我不放置等待,则会出现未定义的错误。但这里的情况并非如此,因此脚本正常退出,并且数据库写入在后台同时发生。


现有答案已经详细解释了原因forEach不应该以它的使用方式与 Promise 一起使用。forEach回调不考虑返回的承诺并破坏承诺链。async..await需要与使用for..of评估一系列的承诺或与Promise.all and map并行评估。

Jest 支持 Promise 并期望从异步函数返回的 Promise (it等)表示该函数中发生的异步进程已经结束。

一旦 Jest 完成测试,它就会检查是否存在阻止 Node 退出的打开句柄。由于 Jest 没有返回并链接 Promise,因此它们所代表的流程会阻止 Jest 完成测试流程。

该问题由上述错误消息表示:

测试运行完成后,Jest 一秒钟都没有退出。

这通常意味着存在未完成的异步操作 在你的测试中停止了。考虑使用 --detectOpenHandles 运行 Jest 来解决此问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 forEach 和 async/await,对于 Node 和 Jest 的行为不同 的相关文章

随机推荐