Нажатие на массив в многообещающем массиве пуст стороной обещания

David Horn спросил: 13 июня 2018 в 07:37 в: arrays
     findCartItem:function(req,res){    const myArray = [];console.log('=====step:1=====');db.Carts.findAll({
    where: {
        UserId: req.params.user
    }
}).then(data => {
    console.log('=====step:3=====');
for(let i =0;i<data.length;i++){
    db.Products.findOne({
        where: {
            id: data[0].dataValues.ProductInfo
        }
    }).then(cartData => {        console.log('=====step:5=====');
        console.log(cartData.dataValues);
        const createdOn = getDbDate(cartData.dataValues.createdAt);
        let theProduct = {
            id: cartData.dataValues.id,
            userId: cartData.dataValues.userId,
            productName: cartData.dataValues.productName,
            serialNumber: cartData.dataValues.serialNumber,
            category: cartData.dataValues.category,
            price: cartData.dataValues.price,
            productDescription: cartData.dataValues.productDescription,
            condition: cartData.dataValues.condition,
            warranty: cartData.dataValues.warranty,
            packaging: cartData.dataValues.packaging,
            userUploadImage1: cartData.dataValues.userUploadImage1,
            userUploadImage2: cartData.dataValues.userUploadImage2,
            status: cartData.dataValues.status,
            verified: cartData.dataValues.verified,
            createdAt: createdOn
        };
        console.log('=====step:6=====');
        myArray.push(theProduct);
        /*now array is being populated*/
        console.log(myArray)
    });
}
    console.log('=====step:4=====');/*even at this point, array hasn't been populated*/
 res.send(myArray)
}).catch(err => console.log(err));console.log('=====step:2=====');/*at this point array hasn't been populated yet*/
console.log(myArray);    }

Я не могу понять, почему за пределами обещания массив выгружает его содержимое. Любая помощь с благодарностью. Код сначала определяет массив при точечном проверке всех продуктов, которые пользователь имеет в своей тележке с его пользователем, и, следовательно, он принимает все продукты, которые у него есть (для этого я вынул цикл до тех пор, пока i выяснить, почему его не работает) в корзине дБ. то он берет все эти данные и находит все детали продуктов, которые есть у каждого продукта. затем он добавляет правильный формат даты и подталкивает его к массиву, но с другой стороны обещает, что он ушел.

2 ответа

Есть решение
dasfdsa ответил: 13 июня 2018 в 09:22

Я думаю, что проблемы возникают из-за отсутствия понимания того, что последний console.log(myArray) (шаг 2) не выполняется после myArray.push() (шаг 6), скорее, до любого из then () callback были вызваны.

Я аннотировал ваш код несколькими журналами шагов, которые могли бы помочь лучше понять:

function findCartItem (req, res) {    const myArray = [];    console.log('=====step:1=====');    db.Carts.findAll({
        where: {
            UserId: req.params.user
        }
    }).then(data => {
        console.log('=====step:3=====');
        db.Products.findOne({
            where: {
                id: data[0].dataValues.ProductInfo
            }
        }).then(cartData => {            console.log('=====step:5=====');
            console.log(cartData.dataValues);
            const createdOn = getDbDate(cartData.dataValues.createdAt);
            let theProduct = {
                id: cartData.dataValues.id,
                userId: cartData.dataValues.userId,
                productName: cartData.dataValues.productName,
                serialNumber: cartData.dataValues.serialNumber,
                category: cartData.dataValues.category,
                price: cartData.dataValues.price,
                productDescription: cartData.dataValues.productDescription,
                condition: cartData.dataValues.condition,
                warranty: cartData.dataValues.warranty,
                packaging: cartData.dataValues.packaging,
                userUploadImage1: cartData.dataValues.userUploadImage1,
                userUploadImage2: cartData.dataValues.userUploadImage2,
                status: cartData.dataValues.status,
                verified: cartData.dataValues.verified,
                createdAt: createdOn
            };
            console.log('=====step:6=====');
            myArray.push(theProduct);
            res.send(myArray);
            /*now array is being populated*/
            console.log(myArray)
        });        console.log('=====step:4=====');
        /*even at this point, array hasn't been populated*/
        console.log(myArray)
        console.log(data[1].dataValues)    }).catch(err => console.log(err));    console.log('=====step:2=====');
    /*at this point array hasn't been populated yet*/
    console.log(myArray);
}

Ниже приведена версия async / await, которая немного проще понять.

async function findCartItem(req,res) {
    const myArray = [];    let data = await db.Carts.findAll({
        where: {
            UserId: req.params.user
        }
    });    let cartData = await db.Products.findOne({
        where: {
            id: data[0].dataValues.ProductInfo
        }
    });    const createdOn = getDbDate(cartData.dataValues.createdAt);
    let theProduct = {
        id: cartData.dataValues.id,
        userId: cartData.dataValues.userId,
        productName: cartData.dataValues.productName,
        serialNumber: cartData.dataValues.serialNumber,
        category: cartData.dataValues.category,
        price: cartData.dataValues.price,
        productDescription: cartData.dataValues.productDescription,
        condition: cartData.dataValues.condition,
        warranty: cartData.dataValues.warranty,
        packaging: cartData.dataValues.packaging,
        userUploadImage1: cartData.dataValues.userUploadImage1,
        userUploadImage2: cartData.dataValues.userUploadImage2,
        status: cartData.dataValues.status,
        verified: cartData.dataValues.verified,
        createdAt: createdOn
    };
    console.log(myArray);
    console.log(data[1].dataValues);
    res.send(myArray);}
David Horn ответил: 13 июня 2018 в 09:13
как бы я получил массив, чтобы заполнить, поэтому я могу отправить его на передний конец
dasfdsa ответил: 13 июня 2018 в 09:15
res.send(myArray) после шага 6
David Horn ответил: 13 июня 2018 в 09:19
Я вернул весь свой код, но массив пуст в res.send
dasfdsa ответил: 13 июня 2018 в 09:23
Я редактировал свой код. Попытайтесь, я думаю, это должно сработать. Кроме того, если вы можете перевести es7, вы можете использовать версию async / wait, которая проще понять
jfriend00 ответил: 13 июня 2018 в 02:08
В этом коде отсутствует сообщение об ошибке при возникновении ошибки. Для версии await требуется try/catch, а версия, не ожидающая, должна просто отправить ответ в .catch().
estus ответил: 13 июня 2018 в 09:21

Обещания не правильно привязаны и вложены без уважительной причины (так называемый обратный ад, что обещание должно помочь). Это приводит к состоянию гонки и неправильной обработке ошибок.

push для массива результатов, скорее всего, не нужен; если есть несколько обещаний для решения, они, вероятно, должны обрабатываться с помощью Promise.all для параллельной работы и получения результатов сразу.

Вместо:

  db.Carts.findAll(...).then(data=>{
    for(let i =0;i<data.length;i++){
      db.Products.findOne(...).then(cartData=>{
        ...
        myArray.push(theProduct);
      });
    }
    console.log(myArray);
  }).catch(err =>console.log(err));

Это должно быть:

  db.Carts.findAll(...).then(data=>{
    const cartPromises = [];
    for(let i =0;i<data.length;i++){
      const cartPromise = db.Products.findOne(...);
      cartPromises.push(cartPromise);
    }
    return Promise.all(cartPromises);
  }).then(cartResults=>{
     // process cart results array and get products array
     res.send(products);
  }).catch(err =>console.log(err));

Каждое обещание, которое существует, должно быть привязано где-то, а цепочка должна заканчиваться на catch.

David Horn ответил: 13 июня 2018 в 09:21
даже когда вы пытаетесь, что массив все еще пуст, и я поставил цикл, в который я вернулся, и поместил полную версию кода с res.send в
estus ответил: 13 июня 2018 в 09:22
@DavidHorn Я обновил код с помощью цикла, в соответствии с изменениями в вопросе.

Дополнительное видео по вопросу: Нажатие на массив в многообещающем массиве пуст стороной обещания

Build a Node.js App With Sequelize [1] - Connection & Model

Node.js + Passport.js + Sequelize.js

4. Веб-сервис с нуля. PostgreSQL и Sequelize