首先,如果这个问题已经有答案了,我很抱歉,但是我已经搜索了这种问题,没有找到有用的东西。
我正在开发一个使用mysql npm包查询数据库的NodeJS应用程序。我已经写了几个查询,借助于promise的帮助(因为SQL模块是这样工作的),这些查询都很好。当正常调用查询过程函数get_works(下面定义)时,我没有问题。
然而,当我在Express路由器中调用这个过程函数时,会出现奇怪的行为。
view.get("/works", (req, res) => {
(async () => {
res.json(await get_works());
})()
});
async function get_works(offset=0,limit=6){
let cdc_database = mysql.createConnection({
/*Filled with credentials*/
});
const get_texts = `SELECT TEXID,TXNOM,TXRES FROM TEXTE LIMIT ${limit} OFFSET ${offset};`; // Valid request
/*Two steps: get texts and get authors of each texts*/
cdc_database.connect();
const texts = await database_promise_query(cdc_database, get_texts);
/*This await always have a correct output*/
let text_authors = [];
for(i = 0; i < texts.length; i++){
get_text_authors = `SELECT AUPRE, AUNOM FROM AUTEURS,ECRIT_PAR\
WHERE AUTEURS.AUTID=ECRIT_PAR.AUTID AND TEXID=${texts[i].TEXID};`; // Request is valid
text_authors[i] = (await database_promise_query(cdc_database, get_text_authors));
/* ^^^^^^^^
The await above returns an undefined value randomly when called through the router
*/
if(text_authors[i] === undefined){
console.error(`[get_works] - Server error on ${i}th text's authors`)
text_authors[i] = [{AUPRE: "Prénom", AUNOM: "Nom"}]
}
}
cdc_database.end();
return works_to_JSON(texts, text_authors)
}
有时,对数据库的查询将没有未定义的值,但一旦有一个未定义的值,后面的所有值也都是未定义的。
Example trace log
(1st call, 3 errors)
[
[ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ],
[ RowDataPacket { AUPRE: 'xxx', AUNOM: "xxx" } ],
[ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ],
[ { AUPRE: 'Prénom', AUNOM: 'Nom' } ],
[ { AUPRE: 'Prénom', AUNOM: 'Nom' } ],
[ { AUPRE: 'Prénom', AUNOM: 'Nom' } ]
]
(2nd call, no error)
[
[ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ],
[ RowDataPacket { AUPRE: 'xxx', AUNOM: "xxx" } ],
[ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ],
[ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ],
[ RowDataPacket { AUPRE: 'xxx', AUNOM: "xxx" } ],
[ RowDataPacket { AUPRE: 'xxx', AUNOM: 'xxx' } ],
]
这是我的promise包装器:
function database_promise_query(database, query){
return new Promise(res => {
database.query(query, (error, results, fields) => {
if(error) {res(undefined); console.log(error)}
res(results);
})
})
}
然而,像这样在路由器之外调用这个函数却非常顺利:
(async () => {
await get_works(0, 10);
await get_works(10, 10);
await get_works(20, 10);
await get_works(30, 10);
})()
我是不是漏掉了什么?我认为所有的查询都是正确的,因为我可以得到想要的结果,问题可能在于我的异步/等待处理。感谢您能提供的所有帮助。
根据@tromgy的建议,我重写了promise包装器。
function database_promise_query(database, query){
return new Promise((res, rej) => {
database.query(query, (error, results, fields) => {
if(error) {rej(error); throw new Error(error)}
console.log("Received response", results)
res(results);
})
})
}
然而,拒绝从未发生(这是合理的,因为数据库中没有匹配的数据)。为了清理日志,我禁用了另一个使用不同数据库连接的类似请求的路由器。删除这个路由器也解决了这个bug。我不知道这是怎么可能的(也许一个变量被声明为全局的,所以我会寻找这种问题)。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
如图所示,问题是一个共享的循环计数器。我的一个同事在迭代之前忘记添加
let关键字,所以 for 循环跳跃了数值。我现在讨厌这个 JavaScript 特性。谢谢帮助!