Как зациклить торг mongoDB с обещанием и циклом forEach? Я хочу заполнить массив - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь перебрать элементы в базе данных MongoDB и сохранить значения в массиве. Однако после нескольких часов борьбы я не могу этого сделать.

Вот мой код:

//shopController.js

const Product = require('../models/product');
const User = require('../models/user');


exports.getCart = (req, res, next) => {
    const productIds = [];
    const productsArr = [];
    let userData = null;

    User.findById(req.user._id)
        .then(user => {
            userData = user;
            userData.cart.items.map(prodId => {
                productIds.push(prodId.productId);
            }) 
            console.log(productIds); // [ 5dc1b6ace13a97588620d6c6, 5dc1b6ace13a97588620d6c6 ]
            return productIds;
        })
        .then(prodIds => {
            prodIds.forEach(prodId => {
                Product.findById(prodId)
                    .then(product => {
                        productsArr.push(product);
                    })
                    .catch(err => console.log(err))
            })
            console.log(productsArr); // []
        })
        .catch((err) => {
            const error = new Error(err);
            error.httpStatusCode = 500;
            return next(error);
        });
}

Не против первого вывода, он предназначен для отображения одного и того же идентификатора дважды. Результат, когда я регистрирую productsArr[], всегда является пустым массивом, за исключением того, что я помещаю console.log(productsArr); внутри цикла forEach(), чего я не хочу, потому что он регистрируется слишком часто, и яне может отобразить страницу EJS следующим образом.

Функция визуализации будет выглядеть следующим образом:

res.render('shop/cart', {
                path: '/cart',
                docTitle: 'Cart',
                products: productsArr,
                userData: userData
            });

Я не могу получить products в productsArr[], как толькокогда я пытаюсь получить доступ к productsArr[] за пределами цикла forEach (), у меня появляется пустой массив, поэтому я не знаю, как это сделать.

Есть ли у вас какие-либосовет?

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Вам нужно отобразить его после разрешения Обещаний, используя Promise.prototype.all, другого способа получить заполненный массив productsArr нет.

Попробуйте:

//shopController.js

const Product = require('../models/product');
const User = require('../models/user');


exports.getCart = (req, res, next) => {
    const productIds = [];
//    const productsArr = []; not needed anymore
    let userData = null;

    User.findById(req.user._id)
        .then(user => {
            userData = user;
            userData.cart.items.map(prodId => {
                productIds.push(prodId.productId);
            })
            console.log(productIds); // [ 5dc1b6ace13a97588620d6c6, 5dc1b6ace13a97588620d6c6 ]
            return productIds;
        })
        .then(prodIds => {
            Promise.all(prodIds.map(prodId =>
                Product.findById(prodId)
            ).then(productsArr => {
                res.render('shop/cart', {
                    path: '/cart',
                    docTitle: 'Cart',
                    products: productArr,
                    userData: userData
                });
                console.log(productsArr); // [ ... products ... ]
            }).catch(err => {
                console.log(err);
            })
        })
        .catch((err) => {
            const error = new Error(err);
            error.httpStatusCode = 500;
            return next(error);
        });
}
0 голосов
/ 05 ноября 2019

Вы не ждете, пока ваш продукт обещает быть завершенным, чтобы отобразить ваши данные. Вы можете использовать функцию Promise.all([]) для ожидания нескольких обещаний одновременно.

 .then(prodIds => {
        Promise.all(prodIds.map(prodId => {
                return Product.findById(prodId)
                    .then(product => {
                        productsArr.push(product);
                    })
                    .catch(err => console.log(err))
            })).then(() => {
                console.log(
        })

Здесь мы сопоставляем все идентификаторы продуктов с обещанием (Product.findById), а затем передаем все из них в * 1006. * функция, которая принимает массив.
Затем мы ожидаем разрешения всех обещаний и вызываем функцию then. Таким образом, вы уверены, что все ваши обещания выполнены до печати ваших данных.

...