NodeJS 在循环结束前发送快速响应

wkyowqbh  于 2022-12-03  发布在  Node.js
关注(0)|答案(2)|浏览(114)

关于这个主题有很多问题,我已经读过了大部分,但是我还是无法理解这个问题。我正在尝试将包含文件URL的数组添加到SQL查询的结果中。在NodeJS中,它工作得很好,但是响应发送得太早,在任何文件数组被添加之前。
到目前为止,我已经尝试了promises、异步和同步fs.extra函数、npm异步模块,promisify。它们都很有前途,可能会工作,但有一些关于这个mysql查询和第一个循环,我不明白。这对特别是在我尝试了两个方法https://stackoverflow.com/a/70748789/12498040和我目前所拥有的。一个与承诺将“失败”promises.all,而不是等待他们全部
下面是代码:如何确保最后执行res.json(result)?提前感谢:)

con.query(sql, function (err, result) {
        if (err) throw err;
        for (let i = 0; i < result.length; i++) {
            //these test arrays are being sent to the client
            result[i].test = ["aaa", "bbb", "ccc"]
            fs.existsSync(fichiers_observations + result[i].id_observation, (exists) => {
                if (exists) {
                    fs.readdirSync(fichiers_observations+result[i].id_observation, (err,files) => {
                        if (err) throw err;
                        result[i].files = [];
                        for (const file of files) {
                            //these URL are not being sent to the client
                            result[i].files.push('a URL/' + file)
                        }
                    });
                }
            })
        }
        res.json(result);
    })
u0njafvf

u0njafvf1#

现在您使用的是fx.existsSync()fs.readdirSync(),它们都是 synchronous 操作。这意味着代码的其余部分将在这些函数启动后继续运行。
基本上,解释器将启动这些操作,然后在它们运行的同时继续运行它们后面的代码行,因为这些函数指示代码将“同步”或"同时“运行。这意味着它将在启动同步操作后立即运行res.json()行,这显然不是所需的行为。
如果你想等待这些函数完成,你必须结合使用async/await和这些函数的异步版本。这将导致你的代码"异步“运行,这意味着”不同时“,或者”一行接一行“。
请在此处查看文档:

  • fs.readdir()(您想要的)与fs.readdirSync()(您拥有的)
  • fs.stat()(您可能需要的内容)与fs.existsSync()(您拥有的内容)

我还没有测试您的代码,但是如果这些新函数的实现与同步版本相同,那么您的新代码可能类似于:

con.query(sql, async function (err, result) {
        if (err) throw err;
        for (let i = 0; i < result.length; i++) {
            //these test arrays are being sent to the client
            result[i].test = ["aaa", "bbb", "ccc"]
            try {
                const exists = await fs.stat(fichiers_observations + result[i].id_observation)
                if (exists) {
                    const files = await fs.readdir(fichiers_observations+result[i].id_observation)
                    result[i].files = [];
                    for (const file of files) {
                        //these URL are not being sent to the client
                        result[i].files.push('a URL/' + file)
                    }
                }
            } catch (err) {
                if (err) throw err;
            }
        }
        res.json(result);
})

或者,您可以找到一种使用更多回调的方法来实现这一点,但使用async/await可能更简洁。

hpxqektj

hpxqektj2#

这是最后的代码。await fs.stat总是返回undefined,所以我不得不返回到fs.exists,同时使用await和promisify。现在看起来很简单,但是有很多方法都不起作用,这是一个相当不错的经验。

const readdir = util.promisify(fs.readdir);
const exists = util.promisify(fs.exists);

con.query(sql, async function (err, result) {
    if (err) throw err;
    for (let i = 0; i < result.length; i++) {
        const it_exists = await exists(directory + result[i].id)
        if(it_exists){
            const files = await readdir(directory + result[i].id)
            result[i].files = [];
            for (const file of files) {
                result[i].files.push('a URL/' + file)
            }
        }
    }
    res.json(result)
})

相关问题