为啥我的异步代码在控制器中有效,但在模型中无效?
Posted
技术标签:
【中文标题】为啥我的异步代码在控制器中有效,但在模型中无效?【英文标题】:Why does my async code work in the controller but not in the model?为什么我的异步代码在控制器中有效,但在模型中无效? 【发布时间】:2019-09-21 05:44:09 【问题描述】:我正在使用 bcrypt 3.0.6。我的Model
文件中有以下代码:
User.prototype.validPassword = async function(password)
try
// original code:
// return await bcrypt.compare(password, this.password);
const match = await bcrypt.compare(password, this.password);
console.log(match);
catch(error)
console.log(error);
return false;
;
我从我的控制器调用它:
try
if (!req.body.userName || !req.body.password) throw "Invalid Login"
user = await User.findOne(
where: userName: req.body.userName
)
if (!user) throw "Invalid login"
const match = user.validPassword(req.body.password);
// const match = await bcrypt.compare(req.body.password, user.password);
if (!match) throw "Invalid login";
// build token
...
);
catch(error)
res.status(500).json(
"msg": "Server Error",
"error": error,
)
当我调试它时,match
是undefined
。
如果我在控制器中进行比较,它会按预期工作。我宁愿比较在模型文件中。我在这里做错了什么?
我是 async/await 代码的新手,但我已经成功地使用它在同一个项目中实现了几个其他控制器方法。
【问题讨论】:
尽管将其命名为returnValue
...
@jonrsharpe 该评论显示了我的原始结构。添加了返回值,因此我可以在其中设置一个断点并查看 bcrypt 比较方法返回的值。
你有没有试过在函数调用前加上await
?
【参考方案1】:
我花了一段时间,但我终于能够弄清楚我做错了什么。我使用 async/await 太多了。以下代码按我的预期工作:
User.prototype.validPassword = function(password)
return bcrypt.compare(password, this.password);
;
我错过了bcrypt.compare
返回承诺的事实(或者更直接地说是事实的重要性)。我只需要返回那个承诺并await
它来解决。
在控制器中:
if (!user) throw "Invalid login";
const match = await user.validPassword(req.body.password);
if (!match) throw "Invalid login";
// build token ...
【讨论】:
【参考方案2】:据我在 js 中使用 async/await
并理解它,您应该在您的 validPassword
方法中返回一个承诺。因为该方法使用的是await
,它本身就是一个异步方法,它在控制器的正常流程之外运行。
因此,根据您的代码,我建议将其更改为类似于以下内容:
User.prototype.validPassword = function(password)
return new Promise(async function (resolve, reject)
try
// original code:
// return await bcrypt.compare(password, this.password);
const match = await bcrypt.compare(password, this.password);
console.log(match);
resolve(match)
catch(error)
console.log(error);
reject();
;
和控制器:
try
if (!req.body.userName || !req.body.password) throw "Invalid Login"
user = await User.findOne(
where: userName: req.body.userName
)
if (!user) throw "Invalid login"
try
const match = await user.validPassword(req.body.password);
If (!match) throw "invalid login";
// build token
catch (err)
throw "Server error";
...
);
catch(error)
res.status(500).json(
"msg": "Server Error",
"error": error,
)
作为替代方案,如果匹配为假,您可以拒绝承诺并评估 catch 中的拒绝
【讨论】:
我看不出上面的内容如何表明密码匹配失败。只有抛出错误才会失败。我错过了什么吗? 对不起,我完全误解了 bcrypt.compare 的用法及其返回值。我调整了代码示例。 如果您在下面看到我的解决方案,bcrypt.compare
如果没有提供回调,则已经返回了一个承诺。我想多了。我只需要在我的控制器中返回该承诺和await
即可。感谢您的诚实尝试。它让我走上了正轨。以上是关于为啥我的异步代码在控制器中有效,但在模型中无效?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我的启动 OpenOffice 服务的调用在开发中有效,但在服务器上无效?
为啥此 python 代码在 pyspark 中有效,但在 spark-submit 中无效?
将 ansi 打印到 windows cmd 在 IPython 中有效,但在其他任何地方都无效。为啥?
为啥 CString::LoadString 在我的应用程序的主模块(.exe)中有效,但在我的 extensionDLL 中无效?