Cara terbaik untuk mengendalikan transaksi dengan cekap menggunakan Promises
P粉226667290
P粉226667290 2024-03-30 20:44:23
0
1
509

Saya sedang mencipta kelas utiliti untuk NodeJs untuk membantu saya menguruskan transaksi pangkalan data.

Idea saya adalah untuk mencipta kaedah seperti ini:

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();
        })
}

dan gunakannya seperti ini:

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(....)
    })

Saya berharap ia akan berkesan, tetapi nampaknya hasilnya adalah ini:

beginTransaction
commit
do query 1
do query 2
do query 3

Adakah anda fikir mungkin untuk mencipta fungsi transactionBlock 返回一个承诺,用户可以在其中执行查询,最后,如果所有查询都正常,函数 transactionBlock yang akan melaksanakan komit?

Saya menggunakan ini: npmjs.com/package/promise-mysql

Terima kasih Selamat tinggal

P粉226667290
P粉226667290

membalas semua(1)
P粉512363233

Masalah besar dengan pendekatan semasa anda ialah finally() sentiasa berjalan tanpa mengira sama ada rantaian janji diselesaikan atau ditolak, jadi anda pasti tidak mahu melakukan transaksi di sana.

Saya hanya melihat satu pilihan di sini...memerlukan fungsi panggil balik yang mewakili badan transaksi.

Secara umum, saya juga mengesyorkan menggunakan sintaks async / wait untuk kebolehbacaan yang lebih baik.

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)`
  }
};

Panggil macam ni

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);
}

Jika anda menggunakan Typescript, antara muka dan jenis berikut akan memastikan operasi lancar

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

const transactionBlock: TransactionBlock = async (connectionName, txBody) => {
  // ...
};
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan