簡體   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