【发布时间】:2017-01-22 05:10:01
【问题描述】:
我有一个作为 API 运行的快速服务器,并且我有一个这样加载的中间件:
app.js
const lastActivity = require('./middleware/lastActivity');
app.use(lastActivity);`
中间件/lastActivity.js
module.exports = function(req, res, next) {
if (req.user && isDifferentDay(req.user.last_activity) {
User.findById(req.user.id, (err, user) => {
user.last_activity = Date.now();
user.save((err) => {
// also do another async call to an external service, then
return next();
}
});
}
});
因此,它会检查用户保存的 last_activity 日期是否与今天不同,如果是,则更新用户(我只关心日期,而不关心具体的时间戳)。它还对外部服务进行 API 调用以管理电子邮件营销活动。
但问题是我的网络应用程序在页面加载时同时请求两个资源。这意味着 isDifferentDay 对它们都返回 true,并且用户模型更新了两次,更重要的是,我对速率受限的外部服务进行了两次 API 调用。
一个明显的解决方案是一次只对我的客户执行一个请求,但我真的不想将自己限制在此。我想要的是一种每秒只运行一次中间件的快速“锁”?或者其他我看不到的解决方案。
以 express/node 方式处理此问题的最佳方法是什么?
谢谢。
【问题讨论】:
-
您对
isDifferentDay的指定可能是错误的:在同一页面和同一天连续两次调用它不应该都返回 true(除非在 23:59 收到第一个调用: 59 和下一个在 0:00:00) -
您在会话中将更新后的
last_activity保存在哪里?我认为如果您在if条件之后立即更新会话(req.user.last_activity),就可以了。另一件事 - 使用findByIdAndUpdate而不是 findById 并保存。更清洁,更快。 -
isDifferentDay正确返回,因为两个请求同时运行。运行此函数时,它对两者都返回 true,并继续沿该路径前进。 -
啊,我明白你的意思了@Tom。如果我可以更新会话同步,那应该可以。
-
你可以。而不是应该工作,它会工作:)