我正在为我的API使用express.js开发移动应用程序的后端。
对于此移动应用程序,用户使用手机号码登录,将OTP代码发送到他们的手机,并且他们需要将收到的OTP发送回服务器以进行验证。
当用户首次尝试登录时,他们将其手机号码发布到服务器,然后进行大量处理,然后通过SMS网关向他们发送OTP。
现在,当此请求仍在进行时,我需要等待用户通过POST请求将OTP发送到另一条路由,进行验证,然后在第一个正在进行的POST请求中继续执行相应的步骤。 / p>
经过网上搜索后,我最终决定将verifyOTP路由的app.post方法包装到一个函数中,该函数创建并返回新的Promise,然后对其进行解析或在验证后拒绝它。重新启动服务器后,第一次执行此操作的效果非常好,仅此而已。它仅在第一次运行,然后在随后的连续时间内,没有解决或拒绝应创建的新承诺,并且对登录路径的第一个请求仍在等待。
我尝试了很多类似的事情,例如使该函数包装verifyOTP路由异步,并在路由内部创建promise,而不是将其包装在一个路由中,但仍然没有用。你能帮我吗?
为了找到解决这个问题的方法,我简化了过程,并使用此代码对实际情况进行了模拟,它很好地模拟了问题:
这是模拟第一个请求:
app.get("/test", async function(req, res) {
console.log("Test route\n");
var otpCode = Math.floor(Math.random() * (9999 - 2)) + 1;
var timestamp = Date.now();
otp = {
code: otpCode,
generated: timestamp
};
console.log("OTP code sent: " + otpCode + "\n");
console.log("OTP sent.\n");
res.end();
/* verifyOTP().then(function() {
console.log("Resolved OTP verification\n\n");
res.end();
}).catch(function() {
console.log("Bad\n\n");
res.end();
});*/
});
这是verifyOTP路由:
var otp;
app.post("/verifyOTP", function(req, res) {
console.log("POST request - verify OTP request\n");
var msg;
if ((Date.now() - otp.generated) / 1000 > 30) {
msg = "OTP code is no longer valid.";
res.status(403).json({
error: msg
});
} else {
var submitted = req.body.otp;
if (submitted !== otp.code) {
msg = "OTP code is incorrect.";
res.status(403).json({
error: msg
});
} else {
msg = "Verified.";
res.end();
}
}
console.log(res.statusCode + " - " + res.statusMessage + "\n");
console.log(msg + "\n");
});
仅需提一下,这并不是我服务器中唯一需要OTP验证的地方,尽管验证后发生的事情的实现方式有所不同。因此,如果解决方案仍然可以使代码可重复用于多个实例,我将不胜感激。
答案 0 :(得分:-1)
在我自己进行了更多研究之后,我放弃了对此用例使用Promises的所有方式,而是使用了RxJS的Observables。
尽管我必须进行一些细微的修改,但是它几乎以我想要的方式解决了我的问题。
对于那些偶然发现我的问题并为我遇到的相同问题寻求解决方案的人:
承诺只能被解决或拒绝一次,据我所知,除非承诺函数完成运行,否则您无法使用相同的代码创建一个新的(请纠正我如果我在这个问题上做错了,我将不胜感激,这仅仅是基于我个人的观察和猜测。)除非您创建了一个全新的Promise,否则您将无法再解决它。
在这种情况下,我们正在根据侦听器(或js中所谓的内容)做出一个Promise,因此,除非删除侦听器,否则答应中扭曲的函数将无法完成运行(我认为),并且您将无法创建新的Promise。
另一方面,Observables可以根据需要进行多次重用,请参见this以了解Promises和Observables的比较,以及this提供了一个不错的教程,可以帮助您了解Observables以及如何使用它们。有关如何为节点安装RxJS的信息,请参见this。
但是,请注意-出于某种原因,一旦您订阅了一个observable,传递给observable.subscribe()的函数中使用的变量将保持不变,它不会随着您对观察者路线。因此,除非您找到一种方法将可更改的变量传递到可观察的定义内的observer.next()函数中,否则您将得到错误的结果。