cari

Rumah  >  Soal Jawab  >  teks badan

Cara terbaik untuk mengendalikan transaksi dengan cekap menggunakan Promises

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粉226667290P粉226667290234 hari yang lalu458

membalas semua(1)saya akan balas

  • P粉512363233

    P粉5123632332024-03-31 10:11:13

    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) => {
      // ...
    };
    

    balas
    0
  • Batalbalas