Может ли sequelize.transaction () принять асинхронную функцию в качестве обратного вызова? - PullRequest
1 голос
/ 24 июня 2019

Итак, читая документацию Sequelize по Экземпляр , а также документы о транзакциях , sequelize.transaction() принимает в качестве параметра функцию autoCallback.Документы говорят:

Обратный вызов вызывается с объектом транзакции и должен возвращать обещание.Если обещание выполнено, транзакция совершается;если обещание отклоняется, транзакция откатывается

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

try {
    let result = sequelize.transaction({
            isolationLevel: 'SERIALIZABLE'
        }, async t => {
            // code to run here with await
            let var1 = await Model.find({ transaction: t });
            let var2 = await Model.find({ transaction: t });

            if (var1.id === 1)
                return "Whatever result";
            else
                throw new Error("Something wicked");
        }
    )});

    // Whatever result
    console.log(result);
}catch(e){
    // Something wicked
}

Кажется, это работает отлично.Но это абсолютно недокументировано, и я не видел, чтобы кто-нибудь использовал это.Это нормально, или я столкнусь со случайными проблемами?

Ответы [ 2 ]

1 голос
/ 24 июня 2019

Вы смешиваете стили, если хотите использовать прямую асинхронность / ожидание, см. Ниже. Вы также не передаете транзакцию (t в вашем коде) запросу, поэтому они не будут ее использовать - вы должны передать ее явно в опции transaction. Если вы вносите какие-либо изменения после того, как совершите транзакцию, а затем откатите ее, если появятся какие-либо ошибки. Вы также можете улучшить свой код, запустив запросы одновременно с Promise.all().

// define outside the try/catch so you can rollback if needed
let transaction;
let result;
try {
    transaction = await sequelize.transaction({ isolationLevel: 'SERIALIZABLE' });

    // run concurrently with Promise.all()
    const [ var1, var2 ] = await Promise.all([
       // don't await here, but you have to pass the transaction
       Model.findByPk({ transaction }),
       Model.findOne({ transaction }), // ditto
    ]);

    if (var1.id === 1) {
       result = "Whatever result";
    } else {
       throw new Error("Something wicked");
    }
    // if you need to commit anything...
    // await transaction.commit();
} catch(err) {
    /* if you need to roll back anything...
    if (transaction) {
       await transaction.rollback();
    }
    */
    console.log(err);
}
return result;
1 голос
/ 24 июня 2019

Как @ Берги и @ Николас Тауэр указал в комментариях:

Поскольку асинхронная функция ВСЕГДА возвращает обещание, а функция обратного вызова должна возвращать обещание, это довольно простой ответ.

Да, его можно использовать.

...