Проблема с асинхронным запросом к базе данных - PullRequest
0 голосов
/ 08 апреля 2020

У меня есть кнопка «Оформить заказ», которая вызывает / orderRegistration, которая, в свою очередь, обновляет количество товара на складе в соответствии с заказом и отправляет подтвержденный заказ на электронную почту

const orderStatus = ['Confirmed', 'Not confirmed'];
router.post('/orderRegistration', (req, res) => {
  if (req.session.successAuthentication === true &&
      req.session.isWorker === false) {
    conn.query(`SELECT  orders.id,
                        products.product_id,
                        products.product_name,
                        products.product_amount,
                        order_product.count 
                FROM orders INNER JOIN order_product
                ON orders.id = order_product.order_id INNER JOIN products
                ON order_product.product_id = products.product_id
                WHERE orders.id IN(
                    SELECT id 
                    FROM orders
                    WHERE user_id=${req.session.userId}
                    AND status = '${orderStatus[1]}')
                AND orders.status = '${orderStatus[1]}';`, (err, selProductId) => {
      if (err) {throw err;}
      if (selProductId.length > 0) {
        let dateNow = new Date(); 
        let prepDate = {
          day: (dateNow.getDate() < 10) ? `0${dateNow.getDate()}` : dateNow.getDate(),
          month: ( dateNow.getMonth() + 1 < 10) ? `0${dateNow.getMonth() + 1}` : dateNow.getMonth() + 1,
          year: dateNow.getFullYear(),
          hours: (dateNow.getHours() < 10) ? `0${dateNow.getHours()}` : dateNow.getHours(),
          minutes: (dateNow.getMinutes() < 10) ? `0${dateNow.getMinutes()}` : dateNow.getMinutes()
        };
        let orderDate =  `${prepDate.day}.${prepDate.month}.${prepDate.year} ${prepDate.hours}:${prepDate.minutes}`;
        let productsInOrderHTML = '';
        let totalAmount = 0;
        for (let i = 0; i < selProductId.length; i++) {
          conn.query(`UPDATE products
                      SET products.product_count_stock = products.product_count_stock - ${selProductId[i].count}
                      WHERE products.product_id = ${selProductId[i].product_id}`, err => {
            if (err) {throw err;}
            productsInOrderHTML += `<tr>
                                      <td>
                                        ${selProductId[i].product_name}
                                      </td>
                                      <td>
                                        ${selProductId[i].count}
                                      </td>
                                      <td>
                                        ${selProductId[i].product_amount}
                                      </td>
                                    </tr>`;
            totalAmount +=  selProductId[i].count *
                            selProductId[i].product_amount;
            if(i === selProductId.length - 1) {
              console.log('totalAmount: ' + totalAmount);
            }
          });
        }
      } else {
        res.send('error');
      }
    });        
  } else {
    res.send('error');
  }
});

Но так как вызовы асинхронные, иногда l oop не успевает обновить все продукты и происходит

if(i === selProductId.length - 1) {
    console.log('totalAmount: ' + totalAmount);
}

, то есть иногда totalAmount может успеть обновить все продукты, а иногда нет, и получается, что totalAmount не будет равняться стоимости, за которую пользователь заказал продукт.

Как мне переписать запрос или изменить его, чтобы это больше не повторилось

PS Извините за англи sh, я перевел это через переводчик, потому что я говорю по-русски. Возможно, я тоже что-то упустил, поэтому поправьте меня при необходимости

1 Ответ

1 голос
/ 08 апреля 2020

Запросы к базе данных являются асинхронными, что означает, что eventl oop из nodejs будет передавать их в очередь, а l oop будет продолжаться, поэтому вам придется ждать их

. Попробуйте это

const orderStatus = ['Confirmed', 'Not confirmed'];
router.post('/orderRegistration', async (req, res) => {
    if (req.session.successAuthentication === true &&
        req.session.isWorker === false) {
        await conn.promise().query(`SELECT  orders.id,
                        products.product_id,
                        products.product_name,
                        products.product_amount,
                        order_product.count 
                FROM orders INNER JOIN order_product
                ON orders.id = order_product.order_id INNER JOIN products
                ON order_product.product_id = products.product_id
                WHERE orders.id IN(
                    SELECT id 
                    FROM orders
                    WHERE user_id=${req.session.userId}
                    AND status = '${orderStatus[1]}')
                AND orders.status = '${orderStatus[1]}';`, async (err, selProductId) => {
            if (err) {
                throw err;
            }
            if (selProductId.length > 0) {
                let dateNow = new Date();
                let prepDate = {
                    day: (dateNow.getDate() < 10) ? `0${dateNow.getDate()}` : dateNow.getDate(),
                    month: (dateNow.getMonth() + 1 < 10) ? `0${dateNow.getMonth() + 1}` : dateNow.getMonth() + 1,
                    year: dateNow.getFullYear(),
                    hours: (dateNow.getHours() < 10) ? `0${dateNow.getHours()}` : dateNow.getHours(),
                    minutes: (dateNow.getMinutes() < 10) ? `0${dateNow.getMinutes()}` : dateNow.getMinutes()
                };
                let orderDate = `${prepDate.day}.${prepDate.month}.${prepDate.year} ${prepDate.hours}:${prepDate.minutes}`;
                let productsInOrderHTML = '';
                let totalAmount = 0;
                for (let i = 0; i < selProductId.length; i++) {
                    await  conn.promise().query(`UPDATE products
                      SET products.product_count_stock = products.product_count_stock - ${selProductId[i].count}
                      WHERE products.product_id = ${selProductId[i].product_id}`, err => {
                        if (err) {
                            throw err;
                        }
                        productsInOrderHTML += `<tr>
                                      <td>
                                        ${selProductId[i].product_name}
                                      </td>
                                      <td>
                                        ${selProductId[i].count}
                                      </td>
                                      <td>
                                        ${selProductId[i].product_amount}
                                      </td>
                                    </tr>`;
                        totalAmount += selProductId[i].count *
                            selProductId[i].product_amount;
                        if (i === selProductId.length - 1) {
                            console.log('totalAmount: ' + totalAmount);
                        }
                    });
                }
            } else {
                res.send('error');
            }
        });
    } else {
        res.send('error');
    }
});
...