在javascript中用类方法链有条件地拦截之前的方法

问题描述 投票:0回答:1

我只是想知道是否可以拦截类链中以前的方法,我有这些类

class And {
  client;
  table;
  condition;

  constructor(client, table, condition) {
    this.client = client;
    this.table = table;
    this.condition = condition;
  }

  and(anotherCondition) {
    return this.client.query(
      `SELECT * FROM "${this.table}" WHERE ${this.condition} AND ${anotherCondition};`
    );
  }
}

class Where {
  client;
  table;

  constructor(client, table) {
    this.client = client;
    this.table = table;
  }

  where(condition) {
    return this.client.query(
      `SELECT * FROM "${this.table}" WHERE ${condition};`
    );
  }
}

class Select {
  client;

  constructor(client) {
    this.client = client;
  }

  from(table) {
    return this.client.query(`SELECT * FROM "${table}";`);
  }
}

class Database {
  client;

  constructor(client) {
    this.client = client;
  }

  select() {
    return new Select(this.client);
  }
}

可以做这样的事情吗?

const db = new Database(client);

await db.select().from(users);
//> return all users

await db.select().from(users).where("id = 1");
//> intercept from() method and return all users with a where condition

await db.select().from(users).where("id = 1").and("email like '%gmail%'");
//> intercept previous two methods and run query with additional and condition

await db.select().from(users).where("id = 1").and("email like '%gmail%'").and("type = 'END_USER'");
//> similar with infinite `and` chains

我想要的是能够链接方法,但这也取决于链接哪些方法并根据该方法返回结果。

我读过有关代理和反射的内容,但我无法从中理解任何意义,任何帮助将不胜感激!

javascript class reflection proxy chaining
1个回答
1
投票

由于我们在这里使用承诺,因此很容易推迟我们的决定以检查我们的承诺是否被链接并采取相应的行动。我认为一些通用的包装可以避免这里的手工工作,但不幸的是瑜伽正在等待我:

class Where {
    client;
    table;

    constructor(client, table) {
        this.client = client;
        this.table = table;
    }

    where(condition) {
        return this.client.query(
            `SELECT * FROM "${this.table}" WHERE ${condition};`
        );
    }
}

class Select {
    client;

    constructor(client) {
        this.client = client;
    }

    from(table) {

        let chained = false;

        const promise = new Promise(resolve => {
            // postpone into a microtask
            queueMicrotask(() => resolve(chained || this.client.query(`SELECT * FROM "${table}";`)));
        });

        promise.where = condition => {
            chained = true;
            return new Where(this.client, table).where(condition)
        };

        return promise;
    }
}

class Database {
    client;

    constructor(client) {
        this.client = client;
    }

    select() {
        return new Select(this.client);
    }
}

const client = {
    query(query) {
        console.log('executing query:', query);
        return new Promise(r => setTimeout(() => r(query.includes('id = 1') ? { fname: 'Alexander', lname: 'Nenashev' } : [{ fname: 'Alexander', lname: 'Nenashev' }]), 1000));
    }
}
<script type="module">

const db = new Database(client);

console.log(await db.select().from('users'));

console.log(await db.select().from('users').where('id = 1'));

</script>

© www.soinside.com 2019 - 2024. All rights reserved.