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

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

Node.js Connection terminated before query is finished

问题

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

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

app.post('/envoi', upload.single("fichiercsv"), async(req, res) => {
    let newClient
    try {
        const { identifiant, motdepasse } = req.body
        const clientConfigModifie = {
            ...clientConfigDefaut,
            user: identifiant,
            password: ''
        }
        newClient = new Client(clientConfigModifie)

        await newClient.connect()

        const rows = []
        const buffer = req.file.buffer
        const readableStreamFromBuffer = new stream.Readable()
        readableStreamFromBuffer.push(req.file.buffer)
        readableStreamFromBuffer.push(null)
        await new Promise((resolve, reject) => {
            fastcsv.parseStream(readableStreamFromBuffer, { headers: false })
                .on('data', us => {
                    rows.push(us)
                })
                .on('end', async() => {
                    rows.shift()
                    const usTotal = rows.map(us => us.join("").split(";"))
                    for (const us of usTotal) {
                        await newClient.query("insert into activite.us (numus, gidgeo) VALUES ($1, $2)", [us[0], us[13]])
                    }
                    resolve()
                })
                .on("error", error => console.error(error))
        })
    } catch (e) {
        console.log("erreur lors du traitement", e)
        res.send('<h3>échec de la connexion</h3>')
    } finally {
        try {
            newClient.end()
        } catch (e) {
            console.log(e)
        }
    }
})
  • 如果我省略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:

app.post(&#39;/envoi&#39;, upload.single(&quot;fichiercsv&quot;), async(req, res) =&gt; {
let newClient
try {
const { identifiant, motdepasse } = req.body
const clientConfigModifie = {
...clientConfigDefaut,
user: identifiant,
password: &#39;&#39;
}
newClient = new Client(clientConfigModifie)
await newClient.connect()
const rows = []
const buffer = req.file.buffer
// console.log(buffer) //ok
const readableStreamFromBuffer = new stream.Readable()
readableStreamFromBuffer.push(req.file.buffer)
readableStreamFromBuffer.push(null)
await new Promise( (resolve, reject) =&gt; {
fastcsv.parseStream(readableStreamFromBuffer, { headers: false })
.on(&#39;data&#39;, us =&gt; {
rows.push(us)	
})
.on(&#39;end&#39;, async() =&gt; { 
rows.shift()
const usTotal = rows.map( us =&gt; us.join(&quot;&quot;).split(&quot;;&quot;))
// console.log(us)
for (const us of usTotal) {
await newClient.query(&quot;insert into activite.us (numus, gidgeo) VALUES ($1, $2)&quot;, [us[0], us[13]])
})
resolve()
})
.on(&quot;error&quot;, error =&gt; console.error(error))
})	
}	
catch(e) {
console.log(&quot;erreur lors du traitement&quot;, e)
res.send(`&lt;h3&gt;&#233;chec de la connexion&lt;/h3&gt;`)
}
finally {
try {
newClient.end()
}
catch(e) { 
console.log(e) 
}
}
})
  • 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

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

.on('end', () => {
    rows.shift();
    const usData = rows.map(us => us.join("").split(";"));
    
    const insertPromises = usData.map(us => {
        return newClient.query("INSERT INTO activite.us (numus, gidgeo) VALUES ($1, $2)", [us[0], us[13]]);
    });

    Promise.all(insertPromises)
        .then(() => {
            resolve();
        })
        .catch(error => {
            reject(error);
        });
})
英文:

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.

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

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:

确定