Синхронная запись в БД
День добрый форумчане! Устал бороться в одиночку с «асинхронностью» сии детища NodeJS. Прибегаю к помощи гуру Promises & Multyrequest.
Ситуация такая: Допустим, у нас в базе (юзаю Pg + Sequalize) есть табличка с данными такого вида: ID TYPE COUNTER 1 «one» 1 2 «two» 1 В модели есть методы decCounterByType(type); & incCounterByType(type); и вроде бы все ни чего пока не попробуешь использовать эти методы в цикле. Цикл же имитирует многочисленное обращение к базе, пример: for(let i = 0; i < 1000; i ++) { Model.incCounterByType(«one») .then(res => console.log(`${i}, ${type}, ${res.counter}`)) .catch(console.error); } Понимаем да, что вывод будет хаотичен и не каждое обращение получит правильный ответ, т. е. лог будет выглядеть примерно так: 0, «one», 1 3, «one», 2 1, «one», 4 2, «one», 3 Где то на просторах нашел решение, и да, оно работает, блокирует обращение: let last = Promise.resolve({}) for(let i = 0; i < 1000; i ++) { last = last .then(() => Model.incCounterByType(«one»)) .then(res => console.log(`${i}, ${type}, ${res.counter}`)) .catch(console.error); } в этом случае у нас вывод будет уже: 0, «one», 1 1, «one», 2 2, «one», 3 3, «one», 4 и вроде бы эврика, решение есть! Но, под правильным углом со знаниями работы алгоритма Promise, мы понимаем, что если один из Promise не выполнит «resolve», или выполнит «reject» or «throw» все остальные обращения ждет фиаско. Пока остановился на таком варианте но уверен, за такой костыль будут бить ногами: let last = Promise.resolve({}) for(let i = 0; i < 1000; i ++) { last = last .then(() => Model.incCounterByType(«one»)) .then(res => console.log(`${i}, ${type}, ${res.counter}`)) .catch(Promise.resolve)); } Цель, добиться корректного обращения к БД и синхронный вывод результатов. А как вы блокируете обращения к БД? Спасибо за участие в обсуждении! |
Что вы пытаетесь вообще сделать?
Почему не увеличить сразу все значения 1 запросом? |
Цитата:
|
Если каждый юзер посылает запрос при заходе - каждый юзер получает свой ответ. И на момент ответа - этот ответ верен. В чём тогда проблема?
Чисто чтоб "порядок был" и цифры красивенькие? |
Async/await в помощь
async function foo() { // вернет Promise<undefined> for (let i = 0; i < 1000; i++) { try { const res = await Model.incCounterByType(«one») console.log(`${i}, ${type}, ${res.counter}`) } catch(err) { // обработка ошибки } } } |
stweet, перечитал, прошу прощение.
Не обратил внимание, что у вас это просто имитация. C postgresql не работал, она не блокирует строку во время её обновления? |
Цитата:
record 1 = 1 record 2 = 10 record 3 = 9 record 4 = 11 и т.д. |
Цитата:
|
Цитата:
Пример такой, есть счетчик, равен "3" Если одновременно "два" юзера жмякнут на "поднять" оба получают "4". А в базе стоит "5" - !неудачный пример! Если два юзера одновременно зарегистрируются, счетчик идти у них будет не по порядку. - Скорее я об этом. |
let GLOBAL_ITER = 0; function iter() { return new Promise((resolve) => { setTimeout(() => { GLOBAL_ITER++; resolve(GLOBAL_ITER); }, 1e3); }); } async function test() { for (let i = 0; i < 5; i++) { try { const curGlobalIter = await iter(); console.log(curGlobalIter) } catch(err) { } } } test().then(() => console.log('done')); как вы можете понять, я увижу постепенно появившиеся с delay 1с 1 2 3 4 5 done |
Часовой пояс GMT +3, время: 16:13. |