NodeJS Promise 在随机情况下返回 undefined 值
P粉321584263
P粉321584263 2024-01-16 14:46:41
0
1
456

首先,如果这个问题已经有答案了,我很抱歉,但是我已经搜索了这种问题,没有找到有用的东西。

我正在开发一个使用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);
})()

我是不是漏掉了什么?我认为所有的查询都是正确的,因为我可以得到想要的结果,问题可能在于我的异步/等待处理。感谢您能提供的所有帮助。

编辑 1

根据@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。我不知道这是怎么可能的(也许一个变量被声明为全局的,所以我会寻找这种问题)。

P粉321584263
P粉321584263

全部回复(1)
P粉063862561

如图所示,问题是一个共享的循环计数器。我的一个同事在迭代之前忘记添加 let 关键字,所以 for 循环跳跃了数值。

我现在讨厌这个 JavaScript 特性。谢谢帮助!

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板