使用forEach和async/await,对节点和Jest的行为有所不同 [英] using forEach and async/await, behaves different for node and Jest

查看:100
本文介绍了使用forEach和async/await,对节点和Jest的行为有所不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a function that writes data to a mongodb, like so:

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

如果我在节点脚本中运行它,则可以正常工作.但是,当我尝试在Jest的 beforeAll 中使用它时,我从Jest得到了这个异步错误:

This works fine if I run it in a node script. But when I tried to use it in Jest's beforeAll I got this async error from Jest:

测试运行一秒钟后,Jest没有退出.这通常意味着存在一些异步操作在测试中停止了.

Jest did not exit one second after the test run has completed. This usually means that there are asynchronous operations that weren't stopped in your tests.

经过一些故障排除后,我发现是 forEach 引起了麻烦.使用for循环解决了此问题:

after some troubleshooting I found out that forEach was causing the trouble. Using a for loop solved this problem:

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

Searching for this problem I came across this article: https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404

那里的解释很合理,但它给我留下了一些问题:

The explanation there made sense, but it left me with some questions:

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

修改

阅读所有评论后,我意识到我的第一个问题有点胡说八道.通常,我将异步函数的结果分配给一个变量,如果我不等待,则会出现未定义的错误.但这不是这种情况,因此脚本可以正常退出,并且数据库写入会在后台同时发生.

After reading all the comments, I realise my first question was a bit nonsense. Normally I assign the result of an async function to a variable, and if I don't put await, there will an undefined error down the line. But that's not the case here, so script exits normally and the db writes happen concurrently in the background.

推荐答案

现有答案已经详细说明了为什么不应该将 forEach 与诺言一起使用. forEach 回调不考虑返回的诺言,并中断诺言链. async..await 需要与 for..of 一起使用,以评估承诺,或者与 Promise.all map 进行并行评估.

The existing answer already explains in detail why forEach shouldn't be used with promises the way it's used. forEach callback doesn't take returned promises into account and breaks promise chain. async..await needs to be used with for..of to evaluate promises in series or with Promise.all and map to evaluate in parallel.

Jest支持promise,并期望从异步函数( it 等)返回的promise表示此函数中发生的异步过程已经结束.

Jest supports promises and expects that a promise that is returned from asynchronous function (it, etc) signifies that asynchronous process that occurred in this function has ended.

一旦Jest完成测试,它将检查是否存在阻止Node退出的打开句柄.由于Jest并未返回承诺并将其链接起来,因此它们所代表的过程会阻止Jest完成测试过程.

Once Jest finishes a test, it checks if there are open handles that prevent Node from exiting. Since promises weren't returned and chained by Jest, processes that they represent prevent Jest from finishing test process.

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

This problem is represented by said error message:

测试运行一秒钟后,Jest并没有退出.

Jest did not exit one second after the test run has completed.

这通常意味着有些异步操作不是在测试中停止了.考虑使用--detectOpenHandles运行Jest解决此问题.

This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with --detectOpenHandles to troubleshoot this issue.

这篇关于使用forEach和async/await,对节点和Jest的行为有所不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆