vendredi 23 juillet 2021

wrap result of method to an intermediate object which deferred execution of original method

pseudocode:

class Transaction {
    withTransaction(trx);
    exec()
}

class Test {
    @somedecorator 
    getUserById(id) {
        return this.trx(this.tableName).where({ id });
    }
}

const inst = new Test()
const res = inst.getUserById(1);
res.withTransaction(myTrx);// call `this.trx(this.tableName).where({ id });` with `myTrx`  
res.exec()// return result of `this.trx(this.tableName).where({ id });` with default trx

Example in plane JS what behavior I want to get

class BaseRepo {
    constructor(tableName, trx) {
        this.tableName = tableName;
        this.trx = trx
    }

}
function getUserByIdFn(id) {
    return this.trx() + `(id number => ${id})`;
}

function decorateMethod(fn, self){
    return (...args) => {
        return {
            withTransaction(trx) {
                return fn.call({
                    ...self,
                    trx,
                },...args)
            },
            then(resolve) {
                return resolve(fn.call(self, ...args));
            }
        }
    }
}
class UserRepo extends BaseRepo {
    constructor(trx) {
        super('user', trx)
    }
    getUserById = decorateMethod(getUserByIdFn, this);
}
// trx here is function for simplicity 
const user = new UserRepo(() => 'original function  result');
(async function main() {
    const result1 = await user.getUserById(1);
    console.log(result1); // original function  result(id number => 1)
    const result2 = user.getUserById(3);
    const t = result2.withTransaction(() => 'another call'); 
    console.log(t); // another call(id number => 3)
})()

I need some approach to wrap getUserById result to in Transaction object which deferred execution of original method. I know how todo that with plane Js, but how do it in Typescript with all typing. Is it possible to do somehow? Some best practice?

Aucun commentaire:

Enregistrer un commentaire