Как обновить массив в MongoDB, используя mon goose? - PullRequest
0 голосов
/ 23 марта 2020

У меня есть две схемы: Пользователь и Продукт. Схема пользователя - это место, где я храню весь идентификатор продукта и количество товаров, добавленных пользователем в корзину.

enter image description here

Когда пользователь отправляет запрос в «/ checkout», он должен обновить количество и затем удалить его из корзины. У меня возникла проблема, когда при оформлении заказа количество не обновляется.

router.post('/checkout', auth, catchAsync(async (req, res) => {
    const user = await User.findById(req.session.userId);
    const err = [];
    if (user && user.products.length > 0) {

        user.products.map(async (product) => {
            let total = 0;
            const p = await Product.findById(product.productID);

            if (p.quantity > 0 && p.quantity > product.quantity) {
                console.log('IN');
                total = p.quantity - product.quantity;
                console.log(total);

                await Product.findOneAndUpdate({ _id: product.productID }, { $set: { quantity: total } });
            } else {
                err.push(`Item, ${p.name} is sold out`);
            }
        });
        await User.findOneAndUpdate({ _id: req.session.userId }, { $set: { products: [] } });
        if (err.length) {
            return res.status(500).json({ message: err });
        }
        return res.status(200).json({ message: 'OK' });
    }
    return res.status(200).json({ message: 'Empty cart' });
}));

Схема пользователя:

enter image description here

Продукт Схема:

Product

1 Ответ

1 голос
/ 23 марта 2020

Я считаю, что проблема в вашем коде заключается в функции user.products.map(...), потому что вы никогда не ждете разрешения всех обещаний, которые вы создаете на карте.

Другими словами, функция map возвращает массив ожидающих обещаний, но он не будет ждать их выполнения, и поэтому выполнение продолжается до тех пор, пока остальная часть кода не достигнет res.status(...), прежде чем какой-либо код в map будет выполнен.

У вас есть разные варианты ее решения, но в основном вам нужно позаботиться о массиве обещаний, возвращаемых функцией map, и дождаться их завершения, прежде чем завершать код. * async/await * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 101 * * * * * * * * * Я обычно использую функцию * Promise.all(), которая возвращает одно обещание из массив обещаний, и поэтому вы можете подождать, пока код в map не будет выполнен параллельно для каждого элемента в массиве (т.е. product в вашем случае). Подробнее об этом можно прочитать в документации MDN .

// ...

let promisesArray = user.products.map(async product => {...});
// promisesArray should look like: [Promise { <pending> }, Promise { <pending> }, … ]

// Using Promise.all we wait for each of them to be done in parallel
await Promise.all(promisesArray);

// Now you are certain the code in the map has been executed for each product

// ...

Хорошей практикой также является использование блока try {} catch(err) {} вокруг Promise.all() для обработки случаев отклонения некоторых обещаний. .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...