Транзакции базы данных происходят параллельно, а не последовательно в цикле - PullRequest
1 голос
/ 29 января 2020

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

 app.post('/create', Authenticate, async (req, res) => {
  const {
    products,
  } = req.body;
  const trxProvider = knex.transactionProvider();
  const trx = await trxProvider();

  try {
    const formattedProduct = await Promise.all(products.map(async (product) => {

     // Get Current value
      const warehouseProducts = await trx('warehouse_products')
        .select('available_qty as qty')
        .where('product_code', product.product.code)
        .first();

      const finalQty = warehouseProducts.qty - product.orderQty;

     // Update database
      await trx('warehouse_products')
        .update({ available_qty: finalQty })
        .where('product_code', product.product.code);
    }));
    await trx('ordered_products')
      .insert(formattedProduct);
    trx.commit();
    console.log('Transaction successful');
    return send(res, 201, { success: true });
  } catch (err) {
    console.log(err);
    trx.rollback();
    const errors = {};
    errors.message = 'something went wrong';
    return send(res, 500, errors);
  }
});

Проблема возникает, когда я пытаюсь обновить ту же строку таблицы warehouse_products в l oop. В l oop первоначально значение кол-во берется из таблицы warehouse_products для конкретного товара, затем выполняется операция арифметического c и значение кол-во обновляется.

В идеале, если обе итерации обращаются к одной и той же строке, начальное значение qty второй итерации должно быть тем, что обновляла первая итерация. Однако проблема в том, что вторая итерация также начинается с начального значения первой итерации. Похоже, что обе итерации происходят параллельно друг другу, а не последовательно.

Ответы [ 3 ]

2 голосов
/ 29 января 2020

Поскольку вы используете Promise.all, это должно происходить параллельно. Для последовательной обработки измените этот код

await Promise.all(products.map(async (product) => {
// logic here
});

на

for(const product of products) {
  // logic here
}
0 голосов
/ 29 января 2020

, если вы не хотите использовать внешнюю библиотеку, такую ​​как Bluebird или Async

, вы можете go с простым для al oop следующим образом

let delay = (t) => new Promise((resolve) => {
	setTimeout(() => {
		return resolve(new Date().getMilliseconds())
	}, t*1000);
});

let array = [1,1,1,1];

//using simple for loop
async function test() {
	let out = [];
	for (let i = 0; i < 4; i++) {
		const res = await delay(array[i]);
		out.push(res);
	}
	return out;
}

test().then(res => {
	console.log(res)
})
0 голосов
/ 29 января 2020

Посмотрите определение для Promise.all ()

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

...