因此,我最近try 创建一个预订网站,您可以在其中 Select 您希望预订的日期.然后向/api/v1/reserve发送请求,判断数据是否有效.生成条带支付意图,将预订保存到数据库,并将支付意图id发送到前端(用于确认).我的问题是,如果两个客户同时单击"发送",他们都会为不应该发生的相同日期付款.

router.post("/reservation", async (req, res) => {

    //Check if everything is in the reqest
    if (!req.body?.name || !req.body?.phone || !req.body?.date) return res.sendStatus(400);
    if (!req.body.phone.match(/^[+]{0,1}[4]{1,2}[8][\s0-9]*$/)) return res.status(400).json({
        type: ErrorTypes.PHONE
    });


    //Validating date
    const reservationDate = new Date(req.body.date);
    if (reservationDate < new Date()) return res.status(400).json({
        type: ErrorTypes.DATE
    });
    //Checking if date is already reserved
    if (await checkIfDateReserved(reservationDate)) return res.status(400).json({
        type: ErrorTypes.RESERVED
    })
    //if reservation date is weekend raise the price ????
    const estimatedPrice = reservationDate.getDay() == 6 || reservationDate.getDay() == 0 ? 3500 : 2000;
    try {
        //Create payment intet
        const intent = await stripe.paymentIntents.create({
            amount: estimatedPrice,
            currency: "PLN",
            payment_method_types: ['card']

        });

        const document = new ReservationModel({
            name: req.body.name,
            reservationDate: reservationDate,
            phone: req.body.phone,
            complete: false,
            intentId: intent.id
        });
        await document.save();
        //If everything went smoothley, send the secret to the client
        //Send the client the intent secret to confirm the payment
        res.json({ clientSecret: intent.client_secret });


    } catch (error) {
        res.status(500);
    }

});

基本上,这两个进程在不同的线程中并行运行,它们判断日期是否同时保留,并同时保留.如何使数据库在处理另一个保存请求之前等待第一个保存请求完成?reservationDate字段是唯一的,但MongoDB似乎仍然忽略了它.

另外,我也想过使用事务处理,但我真的不知道它们在这里如何apply.

推荐答案

所以我最后用了this道题的答案,多亏了0x1C1B.互斥最终工作得很好.如果有人需要,留下代码.

const mutex = new Mutex();

router.post("/reservation", async (req, res) => {

    //Check if everything is in the reqest
    if (!req.body?.name || !req.body?.phone || !req.body?.date) return res.sendStatus(400);
    if (!req.body.phone.match(/^[\s0-9]{9,11}/)) return res.status(400).json({
        type: ErrorTypes.PHONE
    });


    //Validating date
    const reservationDate = new Date(req.body.date);
    if (reservationDate < new Date()) return res.status(400).json({
        type: ErrorTypes.DATE
    });
    await mutex.lock(); //Lock the mutex to avoid processing two reservations at once
    //Checking if date is already reserved
    if (await checkIfDateReserved(reservationDate)) {
        mutex.release(); //Release the mutex so other requests can continue
        return res.status(400).json({
            type: ErrorTypes.RESERVED
        })
    }
    //if reservation date is weekend raise the price ????
    const estimatedPrice = reservationDate.getDay() == 6 || reservationDate.getDay() == 0 ? 3500 : 2000;
    try {
        //Create payment intet
        const intent = await stripe.paymentIntents.create({
            amount: estimatedPrice,
            currency: "PLN",
            payment_method_types: ['card']

        });

        const document = new ReservationModel({
            name: req.body.name,
            reservationDate: reservationDate,
            phone: req.body.phone,
            complete: false,
            intentId: intent.id
        });
        await document.save();
        //If everything went smoothley, send the secret to the client
        //Send the client the intent secret to confirm the payment
        res.json({ clientSecret: intent.client_secret }); //Send the client_secret required for payment confirmation
        //If the confirmation doesn't go through in 5 minutes the reservation is canceled due to "createdAt" field in the schema (see ../../schemas/Reservation.ts)
        //If the payment goes through the automatic deletion is cancelled (see index.ts:59)
        mutex.release(); //Release mutex after reservation has been saved to db
        //So other users can't reserve it

    } catch (error) {
        res.status(500);
        mutex.release();
    }

});

Node.js相关问答推荐

Inno Setup如何在现有文本文件中追加新内容

使用 Google Drive API 按文件夹 ID 检索文件夹的内容

使用 axios 和 Cheerio (Node js) 抓取 google 搜索

当API返回400状态代码时,使用Reactjs fetch获取错误消息

在mongoose虚拟属性中处理异步操作

Google App Engine 突然不允许我部署我的 node.js 应用程序

安装样式组件时出现react 错误

Mongoose post中间件触发deleteMany

如何使用对象中的常量值验证字符串字段?

BrowserRouter 无法渲染组件

node Axios 创建全局令牌变量以在单独的变量头中使用

带有事件网格的 Azure 函数在没有 ngrok 的情况下在本地运行

NestJS TypeORM 可选查询不起作用

如何在拦截器中发送不同的请求?

从 Node.js 应用程序查询 Heroku 托管的 Postgres 数据库时出现自签名证书错误

Node.js 中空函数的简写

npm WARN 不推荐使用 graceful-fs@3.0.8:graceful-fs 版本 3

node.js 在控制台上显示未定义

在 Node.js 中写入 CSV

如何在 NodeJS 中拆分和修改字符串?