繁体   English   中英

Node.js:如何在一个 API 中处理多个请求

[英]Node js: How to handler multiple request in one API

假设这是我的 API:

app.post('/refund', function (req, res) {
        Transaction.findOneAndUpdate({_id: req.body.transaction_id}, {$set: {refund_status: true}}).
        exec(function (err, transaction_status) {
            res.end("Refund successfully")
        }
}

如果两个管理员同时点击退款按钮。 我的客户将收到双倍退款。

那么,如何预防这些问题呢?

只需先获取交易并检查退款状态并更新即可。 如果是虚假退款。 如果它是真的告诉它已经退款了。

  app.post('/refund', function (req, res) {
    // get the transaction first
    Transaction.find({_id: req.body.transaction_id}, function(err, doc) {
      if (doc.refund_status == false) {
         Transaction.findOneAndUpdate({_id: req.body.transaction_id}, {$set: {refund_status: true}}).exec(function(err, transaction_status) {
           res.end("Refund successfully")
      })
      } else { // already refunded
        res.end("Already refunded")
      }
     })
  }

首先,您应该在第一次完成之前禁用两次单击退款按钮的可用性(以获得更好的用户体验)。

为了防止这种情况在后端发生,您可以使用 rate limit the specific route

如果您使用的是 express,您应该查看express-slow-downexpress-rate-limit

一个可能的解决方案是:

const slowDown = require("express-slow-down");

/* app.enable("trust proxy");  only if you're behind a reverse proxy (Heroku, 
                                 Bluemix, AWS if you use an ELB, custom Nginx setup, etc) */
const refundSpeedLimiter = slowDown({
  windowMs: 10 * 1000, // 10 seconds
  delayAfter: 1, // allow the first request to go at full-speed, then...
  delayMs: 1.5 * 1000 // 2nd request has a **1.5s** delay, 3rd has a **3s** delay, 4th gets 4.5s, etc.
});
app.post('/refund', refundSpeedLimiter, function (req, res) {
   // Fetch The Transaction
   Transaction.find({_id: req.body.transaction_id}, function(err, doc) {
   // Check if its not already refunded.
   if (doc.refund_status == false) {
     Transaction.findOneAndUpdate({_id: req.body.transaction_id}, {$set: {refund_status: true}}).exec(function(err, transaction_status) {
       res.end("Refund successfully")
     })
  } else { // already refunded
    res.end("Already refunded")
   }
 })
}

express-rate-limit中所述:

默认情况下,此模块不与其他进程/服务器共享状态。 如果您需要更强大的解决方案,我建议使用外部存储。 有关外部商店的列表,请参阅下面的商店部分。

请注意,默认存储是Memory store ,因此默认情况下它允许多个实例。 如果您打算使用不同的存储(它允许跨多个节点实例使用速率限制 - 就像在集群模式中),您将需要为每个ratelimit实例设置一个自定义键

session.withTransaction()的回调中实现您的退款逻辑。 这将防止并发更新。 不要担心异步的东西; .withTransaction() 正确处理它。

或者,使您的退款逻辑具有幂等性。 也就是说,以多次调用它与调用一次完全相同的方式实现它。 您的设置几乎是幂等的:您从交易 id 开始并将其退款状态设置为 true。 但是,如果您必须在交易已经退款时进行报告,则幂等性可能对您不起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM