Meilleur moyen de gérer efficacement les transactions à l'aide de Promises
P粉226667290
P粉226667290 2024-03-30 20:44:23
0
1
504

Je crée une classe utilitaire pour NodeJs pour m'aider à gérer les transactions de base de données.

Mon idée est de créer une méthode comme celle-ci :

transactionBlock(params) {
    let _db;
    return mySqlConnector.getConnection(params.db)
        .then(db => {
            _db = db;
            console.log(`beginTransaction`);
            return db.beginTransaction()
        })
        .then(() => {
            return Promise.resolve(_db);
        })
        .catch((e) => {
            console.log(`roolback`);
            _db.rollback();
        })
        .finally(() => {
            console.log(`commit`);
            _db.commit();
        })
}

et utilisez-le comme ceci :

const params = {db:"my_db"};
transactionBlock(params)
    .then(db =>{
        console.log(`do query 1`);
        db.insert(....)
        console.log(`do query 2`);
        db.insert(....)
        console.log(`do query 3`);
        db.insert(....)
    })

J'espérais que ça marcherait, mais apparemment le résultat est le suivant :

beginTransaction
commit
do query 1
do query 2
do query 3

Pensez-vous qu'il est possible de créer une fonction transactionBlock 返回一个承诺,用户可以在其中执行查询,最后,如果所有查询都正常,函数 transactionBlock qui effectuera le commit ?

J'utilise ceci : npmjs.com/package/promise-mysql

Merci Au revoir

P粉226667290
P粉226667290

répondre à tous(1)
P粉512363233

Le gros problème avec votre approche actuelle est que finally() toujours s'exécute indépendamment du fait que la chaîne de promesses soit résolue ou rejetée, vous ne voulez donc certainement pas y engager de transaction.

Je ne vois qu'une seule option ici... nécessite une fonction de rappel représentant le corps de la transaction.

En général, je recommande également d'utiliser la syntaxe async / wait pour une meilleure lisibilité.

const transactionBlock = async (connectionName, txBody) => {
  const db = await mySqlConnector.getConnection(connectionName);
  await db.beingTransaction();
  try {
    await txBody(db);
    console.log("commit");
    return db.commit(); // all good, commit
  } catch (err) {
    console.error("rollback", err);
    await db.rollback();
    // keep the rejection chain going by re-throwing the error or a new one
    throw err; // or perhaps `new Error("DB error: " + err.message)`
  }
};

Appelle comme ça

try {
  await transactionBlock("my_db", async (db) => {
    console.log(`do query 1`);
    await db.insert(/* ... */);
    console.log(`do query 2`);
    await db.insert(/* ... */);
    console.log(`do query 3`);
    await db.insert(/* ... */);
  });
} catch (err) {
  console.error("oh no, something went wrong", err);
}

Si vous utilisez Typescript, les interfaces et types suivants garantiront un fonctionnement fluide

type TxBody = (db: Connection) => Promise;
type TransactionBlock = (
  connectionName: string,
  txBody: TxBody
) => Promise;

const transactionBlock: TransactionBlock = async (connectionName, txBody) => {
  // ...
};
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal