Node.js连接在查询完成之前终止

huangapple go评论156阅读模式
英文:

Node.js Connection terminated before query is finished

问题

新手使用node.js。
我在一个托管有PostgreSQL数据库的Windows服务器上设置了一个Node/express服务器。
我的目标是通过一个HTML表单,将用户在自己计算机上选择的csv文件中的数据插入到数据库中。

以下是用户提交表单后执行的js文件部分:

  1. app.post('/envoi', upload.single("fichiercsv"), async(req, res) => {
  2. let newClient
  3. try {
  4. const { identifiant, motdepasse } = req.body
  5. const clientConfigModifie = {
  6. ...clientConfigDefaut,
  7. user: identifiant,
  8. password: ''
  9. }
  10. newClient = new Client(clientConfigModifie)
  11. await newClient.connect()
  12. const rows = []
  13. const buffer = req.file.buffer
  14. const readableStreamFromBuffer = new stream.Readable()
  15. readableStreamFromBuffer.push(req.file.buffer)
  16. readableStreamFromBuffer.push(null)
  17. await new Promise((resolve, reject) => {
  18. fastcsv.parseStream(readableStreamFromBuffer, { headers: false })
  19. .on('data', us => {
  20. rows.push(us)
  21. })
  22. .on('end', async() => {
  23. rows.shift()
  24. const usTotal = rows.map(us => us.join("").split(";"))
  25. for (const us of usTotal) {
  26. await newClient.query("insert into activite.us (numus, gidgeo) VALUES ($1, $2)", [us[0], us[13]])
  27. }
  28. resolve()
  29. })
  30. .on("error", error => console.error(error))
  31. })
  32. } catch (e) {
  33. console.log("erreur lors du traitement", e)
  34. res.send('<h3>échec de la connexion</h3>')
  35. } finally {
  36. try {
  37. newClient.end()
  38. } catch (e) {
  39. console.log(e)
  40. }
  41. }
  42. })
  • 如果我省略finally部分,数据将被插入到数据库中,但连接仍在运行...
  • 使用finally部分,只有第一行us被插入。因此,我收到以下消息:

error: Connection terminated at C:\Apache\balbla\

在这种情况下,似乎newClient.query只运行一次,然后由于某种原因连接被终止但未结束。
我做错了什么?

英文:

Newbie with node.js.
I have set up an Node/express server on a Windows Server hosting a PostgreSQL database.
My goal is to insert in the database the data from a csv file choosen by a user on its own computer, using a HTML form.

Here is the part of the js file executed after the user submits the form:

  1. app.post(&#39;/envoi&#39;, upload.single(&quot;fichiercsv&quot;), async(req, res) =&gt; {
  2. let newClient
  3. try {
  4. const { identifiant, motdepasse } = req.body
  5. const clientConfigModifie = {
  6. ...clientConfigDefaut,
  7. user: identifiant,
  8. password: &#39;&#39;
  9. }
  10. newClient = new Client(clientConfigModifie)
  11. await newClient.connect()
  12. const rows = []
  13. const buffer = req.file.buffer
  14. // console.log(buffer) //ok
  15. const readableStreamFromBuffer = new stream.Readable()
  16. readableStreamFromBuffer.push(req.file.buffer)
  17. readableStreamFromBuffer.push(null)
  18. await new Promise( (resolve, reject) =&gt; {
  19. fastcsv.parseStream(readableStreamFromBuffer, { headers: false })
  20. .on(&#39;data&#39;, us =&gt; {
  21. rows.push(us)
  22. })
  23. .on(&#39;end&#39;, async() =&gt; {
  24. rows.shift()
  25. const usTotal = rows.map( us =&gt; us.join(&quot;&quot;).split(&quot;;&quot;))
  26. // console.log(us)
  27. for (const us of usTotal) {
  28. await newClient.query(&quot;insert into activite.us (numus, gidgeo) VALUES ($1, $2)&quot;, [us[0], us[13]])
  29. })
  30. resolve()
  31. })
  32. .on(&quot;error&quot;, error =&gt; console.error(error))
  33. })
  34. }
  35. catch(e) {
  36. console.log(&quot;erreur lors du traitement&quot;, e)
  37. res.send(`&lt;h3&gt;&#233;chec de la connexion&lt;/h3&gt;`)
  38. }
  39. finally {
  40. try {
  41. newClient.end()
  42. }
  43. catch(e) {
  44. console.log(e)
  45. }
  46. }
  47. })
  • If I omit the finally part, the data are inserted in the database, but the connection is running...
  • With the finally part, only the first row of us is inserted. Thus, I have the message :

error: Connection terminated at C:\Apache\balbla\

In this case, it seems that newClient.query runs one time only then for some reason the connection is terminated but not ended.
What am I doing wrong ?

EDIT : code updated after @I2yscho answer.

答案1

得分: 1

问题是你没有异步处理插入操作。这段代码不是处理这个问题的最佳方式,但它是一个可行的解决方案。我建议你使用某种形式的批量插入来进行一次查询。

  1. .on('end', () => {
  2. rows.shift();
  3. const usData = rows.map(us => us.join("").split(";"));
  4. const insertPromises = usData.map(us => {
  5. return newClient.query("INSERT INTO activite.us (numus, gidgeo) VALUES ($1, $2)", [us[0], us[13]]);
  6. });
  7. Promise.all(insertPromises)
  8. .then(() => {
  9. resolve();
  10. })
  11. .catch(error => {
  12. reject(error);
  13. });
  14. })
英文:

Problem is you don't handle insert operations asynchronously. This code is not a best way how to handle this, but it is working solution. I recommend you to use some sort of bulk insert in one query.

  1. .on(&#39;end&#39;, () =&gt; {
  2. rows.shift();
  3. const usData = rows.map(us =&gt; us.join(&quot;&quot;).split(&quot;;&quot;));
  4. const insertPromises = usData.map(us =&gt; {
  5. return newClient.query(&quot;INSERT INTO activite.us (numus, gidgeo) VALUES ($1, $2)&quot;, [us[0], us[13]]);
  6. });
  7. Promise.all(insertPromises)
  8. .then(() =&gt; {
  9. resolve();
  10. })
  11. .catch(error =&gt; {
  12. reject(error);
  13. });
  14. })

huangapple
  • 本文由 发表于 2023年8月9日 18:02:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76866641.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定