Как обрабатывать несколько запросов (Express.js) с помощью операции вставки mongodb

Контекст

Я следую руководству под названием «Создание безопасной регистрации пользователей и API входа в систему с помощью Express.js, MongoDB и JWT»

Он использует express bcryptjs jsonwebtoken mongoose для создания простого веб-сервера с функцией регистрации/входа.

Проблема

Проблема возникает, когда я отправляю множество запросов на /api/register. Сервер создает множество пользователей с одинаковыми учетными данными.

Код для воспроизведения

Сервер

// Importing required modules
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

// Creating an Express application instance
const app = express();
const PORT = 3000;

// Connect to MongoDB database
mongoose.connect('mongodb://localhost:27017/mydatabase')
    .then(() => {
        console.info('Connected to MongoDB');
    })
    .catch((error) => {
        console.error('Error connecting to MongoDB:', error);
    });

// Define a schema for the User collection
const userSchema = new mongoose.Schema({
    username: String,
    email: String,
    password: String
});

// Create a User model based on the schema
const User = mongoose.model('User', userSchema);

// Middleware to parse JSON bodies
app.use(express.json());

// Route to register a new user
app.post('/api/register', async (req, res) => {
    try {
        // Check if the email already exists
        const existingUser = await User.findOne({email: req.body.email});
        if (existingUser) {
            return res.status(400).json({error: 'Email already exists'});
        }

        // Hash the password
        const hashedPassword = await bcrypt.hash(req.body.password, 10);

        // Create a new user
        const newUser = new User({
            username: req.body.username,
            email: req.body.email,
            password: hashedPassword
        });

        await newUser.save();
        console.info(newUser)
        res.status(201).json({message: 'User registered successfully'});
    } catch (error) {
        console.info('Internal server error')
        res.status(500).json({error: 'Internal server error'});
    }
});

// Start the server
app.listen(PORT, () => {
    console.info(`Server is running on port ${PORT}`);
});

Клиент

(() => {
    const send = () => fetch('http://127.0.0.1:3000/api/register', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            "username": "testuser", "email": "[email protected]", "password": "testpassword"
        })
    }).then()

    for (let i = 0; i < 10; i++) send()
})()

Выход

{
  username: 'testuser',
  email: '[email protected]',
  password: '$2a$10$5Jo01CQ797EuMrujH49Of.OmFY4n6yIX.4VgU8FOEhXRmr.CxHnRy',
  _id: new ObjectId('668cf24a08fa6ed9fbf442d5'),
  __v: 0
}
...9 more users created

🤔 А знаете ли вы, что...
Node.js позволяет создавать веб-приложения в реальном времени с помощью библиотеки Socket.io.


54
1

Ответ:

Решено

Это распространенная проблема при асинхронных операциях. Это как если бы 10 человек одновременно спросили, есть ли свободный стул. Все 10 из них получают ответ «да», но только один из них может на нем сесть.

Чтобы решить эту проблему, вам следует проверить модель.

const userSchema = new mongoose.Schema({
  username: { type: String, unique: true },
  email: { type: String, unique: true },
  password: String,
});