等待forEach循环结束以呈现-Javascript

等待forEach循环结束以呈现-Javascript,javascript,node.js,Javascript,Node.js,我在读关于如何解决这个问题的书,每个人都说我应该使用“异步”和“等待”,但我不知道如何在我的代码中恰当地使用它。(我正在制作一个新的JSON,我应该将它发送到前端,但我需要先等待JSON在forEach循环中准备好,然后在屏幕上渲染) 我试过很多种方法,但没有一种效果好。 如果我犯了一些错误,很抱歉。在调用res.render()之前,您没有正确地等待完成所有异步操作,因此在尝试使用数组时,数组是空的或部分填充。因此,您需要使用承诺来跟踪何时一切都完成了 你有两个选择。您可以并行或按顺序运行所有

我在读关于如何解决这个问题的书,每个人都说我应该使用“异步”和“等待”,但我不知道如何在我的代码中恰当地使用它。(我正在制作一个新的JSON,我应该将它发送到前端,但我需要先等待JSON在forEach循环中准备好,然后在屏幕上渲染)

我试过很多种方法,但没有一种效果好。
如果我犯了一些错误,很抱歉。

在调用
res.render()
之前,您没有正确地等待完成所有异步操作,因此在尝试使用数组时,数组是空的或部分填充。因此,您需要使用承诺来跟踪何时一切都完成了

你有两个选择。您可以并行或按顺序运行所有请求。我将展示这两个方面的示例:

下面是并行处理所有数据库请求。这将链接各种承诺,并使用
Promise.all()
了解它们何时完成。
控件中的结果\u cadastrados
没有任何特定顺序,但这可能比按顺序处理所有内容运行得更快

router.get('/', (req, res) => {
    Controle.find()
        .lean()
        .then(controles => {
            const controles_cadastrados = [];
            Promise.all(controles.map(controle => {
                return Sensor.find({ id_mac: controle.sensor })
                    .lean()
                    .then(sensor => {
                        controle.sensor_nome = sensor[0].nome;
                        return Atuador.find({ id_mac: controle.atuador })
                            .lean()
                            .then(atuador => {
                                controle.atuador_nome = atuador[0].nome;
                                controles_cadastrados.push(controle);

                                console.log(controles_cadastrados);
                            });
                    });
            })).then(() => {
                //wait to send the response
                res.render('controle/controles', {
                    controles: controles_cadastrados,
                });
            });
        }).catch(erro => {
            console.log('Erro ao carregar controles');
            res.sendStatus(500);
        });
});
下面是如何使用
async/await
对操作进行排序:

router.get('/', async (req, res) => {
    try {
        let controles = await Controle.find().lean();
        const controles_cadastrados = [];
        for (let controle of controles) {
            let sensor = await Sensor.find({ id_mac: controle.sensor }).lean();
            controle.sensor_nome = sensor[0].nome;
            let atuador = await Atuador.find({ id_mac: controle.atuador }).lean()
            controle.atuador_nome = atuador[0].nome;
            controles_cadastrados.push(controle);
            console.log(controles_cadastrados);
        }
        //wait to send the response
        res.render('controle/controles', {
            controles: controles_cadastrados,
        });
    } catch(e) {
        console.log(e, 'Erro ao carregar controles');
        res.sendStatus(500);        
    }
});

另外,请注意,此处捕获所有可能被拒绝的承诺或其他错误,并且始终向传入的http请求发送响应,即使出现错误。

在调用
res.render()之前,您没有正确地等待完成所有异步操作
因此,当您尝试使用阵列时,阵列为空或部分填充。因此,您需要使用承诺来跟踪何时一切都完成了

你有两个选择。您可以并行或按顺序运行所有请求。我将展示这两个方面的示例:

下面是并行处理所有数据库请求。这将链接各种承诺,并使用
Promise.all()
了解它们何时完成。
控件中的结果\u cadastrados
没有任何特定顺序,但这可能比按顺序处理所有内容运行得更快

router.get('/', (req, res) => {
    Controle.find()
        .lean()
        .then(controles => {
            const controles_cadastrados = [];
            Promise.all(controles.map(controle => {
                return Sensor.find({ id_mac: controle.sensor })
                    .lean()
                    .then(sensor => {
                        controle.sensor_nome = sensor[0].nome;
                        return Atuador.find({ id_mac: controle.atuador })
                            .lean()
                            .then(atuador => {
                                controle.atuador_nome = atuador[0].nome;
                                controles_cadastrados.push(controle);

                                console.log(controles_cadastrados);
                            });
                    });
            })).then(() => {
                //wait to send the response
                res.render('controle/controles', {
                    controles: controles_cadastrados,
                });
            });
        }).catch(erro => {
            console.log('Erro ao carregar controles');
            res.sendStatus(500);
        });
});
下面是如何使用
async/await
对操作进行排序:

router.get('/', async (req, res) => {
    try {
        let controles = await Controle.find().lean();
        const controles_cadastrados = [];
        for (let controle of controles) {
            let sensor = await Sensor.find({ id_mac: controle.sensor }).lean();
            controle.sensor_nome = sensor[0].nome;
            let atuador = await Atuador.find({ id_mac: controle.atuador }).lean()
            controle.atuador_nome = atuador[0].nome;
            controles_cadastrados.push(controle);
            console.log(controles_cadastrados);
        }
        //wait to send the response
        res.render('controle/controles', {
            controles: controles_cadastrados,
        });
    } catch(e) {
        console.log(e, 'Erro ao carregar controles');
        res.sendStatus(500);        
    }
});

此外,请注意,所有可能被拒绝的承诺或其他错误都会在此处捕获,并且始终会向传入的http请求发送响应,即使出现错误。

谢谢!很好的解释,很有魅力。致以最良好的祝愿。@Donada-如果这回答了您的问题,那么您可以通过单击答案左侧的复选标记向社区表明这一点。这也会为你赢得一些声誉点,因为你遵循了正确的程序。谢谢!很好的解释,很有魅力。致以最良好的祝愿。@Donada-如果这回答了您的问题,那么您可以通过单击答案左侧的复选标记向社区表明这一点。这也将为你赢得一些声誉点在这里遵循正确的程序。