如何在Node.js中使用“异步/等待”和“承诺”进行同步执行?

时间:2019-02-09 13:34:12

标签: javascript node.js async-await es6-promise

作为一个整体,我对于Web开发还很陌生,所以我不太了解Promise和异步/等待。我正在尝试将一个职位发布网站构建为一个项目,但由于无法使特定的代码段按我的意愿工作而陷入困境。

在以下片段中,发布特定职位要求的招聘人员希望查看申请人的与职位要求相关的技能。因此,代码将首先从mongodb集合中获取工作详细信息和有问题的申请人的详细信息。然后,它将尝试先存储申请人所需的技能,然后再将申请人的所有技能存储在技能数组中。仅在将以上所有数据存储在skill []中之后,代码才应使用最后的json进行响应。但是它的行为不像我想要的那样,并且在存储完成之前它没有做出响应。有人可以指导我如何使其“同步”吗?

注意:我删除了所有错误处理,以使代码段更短。另外,申请人在全部5种技能中具有2种必需技能。

router.post('/recruiter/viewApplicant', passport.authenticate('jwt', {session: false}), (req, res, next) => {

    if(req.user.accountType === "Recruiter") {
        skills = [];

        Job.getJobByID((req.body.jobID),(err, job) => {
            User.getUserByEmail(req.body.email,(err, user) => {
                let i =0;
                job.requiredSkills.requirements.forEach(reqSkill => {
                    user.classData.forEach(classDetail => {
                        if(classDetail.classID === reqSkill.class.replace(/ /g, '-')) {
                            ClassData.getClassByclassID(classDetail.classID,(err, classInfo) => {
                                skills.push({
                                    type: 'req',
                                    imgURL: classInfo.imgURL,
                                    skill: classDetail
                                })
                                console.log('req: '+i)
                                i++
                            })
                        }
                    })
                })

                let k=0
                user.classData.forEach(classDetail => {
                    ClassData.getClassByclassID(classDetail.classID,(err, classInfo) => {
                        skills.push({
                            type: 'all',
                            imgURL: classInfo.imgURL,
                            skill: classDetail
                        })
                        console.log('all: '+k)
                        k++
                    })
                })
            }) 

            console.log("Completed");        
            res.json({success: true, msg: "Successful", data: skills});
        })
    }
});

预期结果:

req: 0  
req: 1   
all: 0  
all: 1  
all: 2  
all: 3  
all: 4  
Completed  

实际结果:

Completed  
req: 0  
req: 1  
all: 0  
all: 1  
all: 2  
all: 3  
all: 4  

1 个答案:

答案 0 :(得分:0)

要获取必须使用的代码,请按如下所示移动res.json()调用

            user.classData.forEach(classDetail => {
                ClassData.getClassByclassID(classDetail.classID,(err, classInfo) => {
                    skills.push({
                        type: 'all',
                        imgURL: classInfo.imgURL,
                        skill: classDetail
                    })
                    console.log('all: '+k);
                    k++;
                })
            })
            res.json({success: true, msg: "Successful", data: skills});

在您放置它的地方不起作用,因为对.getJobById()的调用会立即返回。当它完成所需的工作时,您会知道,因为它会调用其回调函数。嵌套的.getUserByEmail()调用也是如此。

async / await和Promise是组织Java回调的方法,因此它们似乎没有嵌套。它们使代码更易于阅读。但是回调仍然是嵌套和异步的。确切解释如何将代码转换为使用Promises和async / await超出了SO答案的范围。简而言之,您应该promisify your asynchronous functions, then you can await their results。熟悉这种用Javascript进行编码的方式绝对值得您花一两天的时间。

专业提示:如果您通过调试器逐步执行此类代码,请大量使用“逐步进入”。