我无法适当地重构代码 [英] I am unable to refactor the code appropriately

查看:62
本文介绍了我无法适当地重构代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

router.get('/',ensureLogin,async (req,res)=>{
    try{
        let result = await Mock.find();
            result.forEach(async (e)=>{
                if(e.attemptedBy.includes(req.user._id)){
                    let a_Mock = await User.findOne({_id:req.user._id,"attemptedMock.setNo":e.setNo},{attemptedMock:1});
                    e.status="Attempted";// not accessible on template as res.render executes first
                    e.marks = a_Mock.attemptedMock[0].totalMarks;  //not accessible
                    console.log(a_Mock.attemptedMock[0].totalMarks);         
                }
                else{
                    e.status = "Unattempted";//it is accessible
                    console.log('else block')
                }
            })
           console.log("second log");
           res.render('dashboard',{mocks:result});//I want this code to be executed when the "result" is updated by "forEach" block
    }catch(e){
        console.log(e);
    }
})

控制台记录为: 1. else block"2.第二个日志"3.res.render已执行"4.总分",得出结论是在if块"之前执行了res.render.语句e.status='Attempted'"所以它不能在模板页面上访问.请告诉我如何以适当的方式重构.

Console logs as : 1. "else block" 2. "second log" 3."res.render executed" 4. "total marks", that concludes that res.render executed before "if block's" statement "e.status='Attempted'" so it is not accessible on template page. Please tell me how to refactor in a proper way.

推荐答案

如果您尝试一次执行一个循环,然后在循环完成后调用 res.render(),那么最简单的方法是使用常规的 for 循环,因为它实际上会等待"对于 await..forEach() 不是 promise-aware 所以,虽然回调本身会在它完成之前等待 await.forEach() 本身不会,它将运行整个循环,然后运行后的下一行,然后每个单独的回调将在稍后完成.这将导致您在任何 .forEach() 回调完成之前调用 res.render().出于这个原因,您几乎永远不想将 .forEach() 与承诺一起使用,因为它只是不知道承诺.相反,使用常规的 for 循环,如下所示:

If you are trying to do your loop one at a time and then call res.render() after the loop is done, then the easiest way to do that is to use a regular for loop as it will actually "wait" for the await. .forEach() is not promise-aware so, while the callback itself will wait for the await before it finishes, .forEach() itself will not and it will run the entire loop and then the next line after it will run and then each individual callback will finish sometime later. That will cause you to call res.render() before any of the .forEach() callbacks are done. For this reason, you pretty much never want to use .forEach() with promises as it's just not promise-aware. Instead, use a regular for loop like this:

router.get('/', ensureLogin, async (req,res) => {
    try {
        let result = await Mock.find();
        for (let e of result) {                
            if (e.attemptedBy.includes(req.user._id)) {
                let a_Mock = await User.findOne({_id:req.user._id,"attemptedMock.setNo":e.setNo},{attemptedMock:1});
                e.status = "Attempted";
                e.marks = a_Mock.attemptedMock[0].totalMarks;  //not accessible
            } else {
                e.status = "Unattempted";    //it is accessible
            }
        }
        console.log("second log");
        res.render('dashboard', {mocks:result});
    } catch(e) {
        console.log(e);
        res.sendStatus(500);
    }
});

另请注意,此代码在 catch 块中发送错误状态.您需要始终对传入的 http 请求发送一些响应.

Note also that this code sends an error status in the catch block. You need to always send some response to the incoming http request.

这篇关于我无法适当地重构代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆