dev*_*ell 2 javascript node.js async-await jestjs
我有一个将数据写入 mongodb 的函数,如下所示:
const writeToDB = async (db, data) => {
const dataKeys = Object.keys(data)
dataKeys.forEach(async key => db.collection(key).insertMany(data[key]))
}
Run Code Online (Sandbox Code Playgroud)
如果我在节点脚本中运行它,效果很好。但是当我尝试在 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])
}
}
Run Code Online (Sandbox Code Playgroud)
搜索这个问题我遇到了这篇文章: https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404
那里的解释很有道理,但它给我留下了一些疑问:
编辑
读完所有评论后,我意识到我的第一个问题有点无稽之谈。通常我将异步函数的结果分配给变量,如果我不放置等待,则会出现未定义的错误。但这里的情况并非如此,因此脚本正常退出,并且数据库写入在后台同时发生。
现有的答案已经详细解释了为什么forEach不应该与 Promise 一起使用它的使用方式。forEach回调不考虑返回的承诺并破坏承诺链。async..await需要与 with 一起使用for..of来串行评估 Promise,或者与Promise.alland 一起map使用来并行评估。
Jest 支持 Promise,并期望从异步函数( 等)返回的 Promiseit表示该函数中发生的异步过程已经结束。
一旦 Jest 完成测试,它就会检查是否存在阻止 Node 退出的打开句柄。由于 Jest 没有返回并链接 Promise,因此它们所代表的流程会阻止 Jest 完成测试流程。
该问题由上述错误消息表示:
测试运行完成后,Jest 一秒钟都没有退出。
这通常意味着测试中存在未停止的异步操作。请考虑使用 --detectOpenHandles 运行 Jest 来解决此问题。