验证功能不等待承诺解决

时间:2020-04-01 12:02:04

标签: javascript asynchronous promise

我正在执行身份验证功能。它实际上适用于硬编码用户,但是当我开始从Firebase获取用户时,事情开始变得异步,并且出现了计时问题。

在这里,我有一种长久以来的Javascript函数,我相信会返回一个承诺。

function authenticate({ username, password }) {
    return users.then((querySnapshot) => {
        return querySnapshot.forEach(doc => {
            let user = doc.data();
            if (user.username.toUpperCase() == username.toUpperCase())
                return bcrypt.compare(password, user.password).then(function (result) {
                    console.log(password);
                    console.log(user.password);
                    console.log(result);
                    if (result) {
                        const token = jwt.sign({ sub: user.id }, config.secret);
                        const { password, ...userWithoutPassword } = user;
                        return {
                            ...userWithoutPassword,
                            token
                        };
                    }
                })
        })
    })
}

控制台日志记录似乎证实了这一承诺。老实说,我复制粘贴了很多内部代码,因此我仍然不确定它是如何工作的,但是promise语法至少是我有信心的。用户从Firebase中拉出并检查用户名和密码是否匹配,if (result)的勇气应该运行。 result确实以true的形式返回,这与我尝试使用的登录名是正确的,但是我的密码表拒绝了我,因为它会在认证方法完成之前继续进行处理。

在另一个Javascript文件中,我有调用该文件的方法。

function authenticate(req, res, next) {
    console.log(req.body);
    userService.authenticate(req.body)
        .then(user => console.log(user))
        //.then(user => user ? res.json(user) : res.status(400).json({ message: 'Username or password is incorrect' }))
        .catch(err => next(err));
}

最近我在异步编程方面学到了很多东西,但这有点违背了我的期望。确定在.then()上执行authenticate()应该运行authenticate(),得到一个承诺,即使它尚未解决,也要等到它解决后再执行其余的语句?当前的问题是该方法继续进行,没有找到user的值,然后抛出400,我认为是具有异步性的问题。谁能解释为什么外部身份验证功能没有等待,我该如何做呢?

2 个答案:

答案 0 :(得分:0)

有两个可能的问题:

forEach的结果

forEach函数返回未定义,请参见Array.prototype.forEach()。如果需要迭代结果,则可以使用Array.prototype.map()

等待承诺

以下语句听起来像代码未正确等待结果:

我的密码表拒绝了我,因为它在身份验证方法完成之前会继续处理。

如果您具有JavaScript承诺,则只有在承诺被解决或拒绝的情况下,才能使用await关键字来继续执行函数。在这里查看示例:https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Operators/await

在您的示例中,authenticate函数如下所示:

async function authenticate(req, res, next) {
  console.log(req.body);
  await userService.authenticate(req.body)
    .then(...)
    .catch(...);
}

请注意asyncawait关键字。这样,它只有在userService.authenticate(..)调用得到完全处理之后才返回。

答案 1 :(得分:0)

Firebase QuerySnapshot具有类型docs的{​​{1}}属性。您可以使用它和Array.find来搜索用户。搜索用户时,还应Array<QueryDocumentSnapshot<T>> await

bcrypt.compare

请考虑改用Firebase身份验证

您的身份验证实现不可靠,并且会将敏感数据传输到每个用户设备,例如function authenticate({ username, password }) { return users.then(async (querySnapshot) => { const { usersDocs: docs } = querySnapshot; const userDoc = usersDocs.find(doc => { return doc.data().username === username; }); if (userDoc) { let user = doc.data(); const pwdCompareResult = await bcrypt.compare(password, user.password); console.log(password); console.log(user.password); console.log(pwdCompareResult ); if (pwdCompareResult ) { const token = jwt.sign({ sub: user.id }, config.secret); const { password, ...userWithoutPassword } = user; return { ...userWithoutPassword, token } } } }) } usersname哈希。 Firebase具有您应该使用的非常可靠的身份验证系统。