JavaScript:像wx.cloud.database一样封装前端数据库操作

JavaScript:像wx.cloud.database一样封装前端数据库操作

前天呢去公司见了一下未来的同事~看了一下现在的业务代码,发现了其中一个有趣的操作。即在前端向统一一个接口做数据库操作,我当时蛮震惊(我本以为的直接字符串SQL语句这样)。后来看了一下发现还是通过request请求的方式完成,不过现有封装是在一个函数中一次条件一次请求,回想小程序的云开发数据库请求,这不是现成的封装例子么!搞起来!

项目使用了click house作为数据库,封装上要和mongoDB有些不同;

1 抽象

要做数据库操作,逃不开“增删改查”四大密字。

我们先定义一个DataBase接口

  • DataBase 包含大部分方法的基类
interface DataBaseInterface {
  form: null | DBForm;
  collection(name: string): DataBase;
  clear(): void;
  where(condition: WhereCondition): DataBase;
  limit(val: number): DataBase;
  orderBy(name: string, sort: OrderBySort): DataBase;
  skip(val: number): DataBase;
  groupBy(name: string): DataBase;
  get(): Promise<DataBaseRes>;
}

出于安全性(和简便)考虑,这里只做查询封装。

这其中类似where(condition: WhereCondition): DataBase;每次调用后会返回本身,实现链式调用。

可以看到,上方还定义了DBForm,WhereCondition,OrderBySort,DataBaseRes这些接口,这些接口的实现如下:

  • DBForm 定义了最终发送请求的payload中的数据项
interface DBForm {
  orderBy?: Array<OrderBy>;
  where?: WhereCondition;
  collection: string;
  limit?: number;
  groupBy: Array<string>;
  skip?: number;
}
interface OrderBy {
  name: string;
  order: OrderBySort;
}

a new interface——OrderBy

这里定义collection是必选项

  • WhereCondition 条件接口
interface WhereCondition {
  [key: string]: any;
}

由于还没有写到,先用any代替;

  • OrderBySort

OrderBySort实际上是TS的枚举对象

enum OrderBySort {
  asc,
  desc,
}
  • DataBaseRes 返回结果
enum DBcode {
  success,
  fail,
}
interface DataBaseRes {
  code: DBcode;
  source: any;
}

2 基本实现

2.1 构造与析构

db的构造是简便的,目前在开始的时候创建form=null即可

class DataBase implements DataBaseInterface {
  form: DBForm | null;
  constructor() {
    this.form = null;
  }
  clear() {
    this.form = null;
  }
  collection(name: string) {
    this.form = Object.create(null);
    this.form!.collection = name;
    return this;
  }
}

2.2 基本功能实现

2.2.1 where

按照接口约定,where函数应该返回一个DataBase,并接收一个WhereCondition;

  where(condition: WhereCondition) {
    if (this.form?.where) {
      throw new Error("already existing[where]");
    }
    this.form!.where = condition;
    return this;
  }
2.2.2 limit&skip

这两应该是最简单滴,limit和skip需要接收一个整数。

  limit(val: number) {
    if (this.form?.limit) {
      throw new Error("already existing[limit]");
    }
    this.form!.limit = val;
    return this;
  }

  skip(val: number) {
    if (this.form?.skip) {
      throw new Error("already existing[skip]");
    }
    this.form!.skip = val;
    return this;
  }
2.2.3 orderBy

orderBy的话,应该按照先后顺序进行排序

如此的话还是使用了数组,虽然对象也是有序的

orderBy(name: string, order: OrderBySort) {
    if (!this.form) throw new Error("none connect");
    if (!this.form.orderBy) {
      this.form.orderBy = [];
    }
    this.form.orderBy.push({ name, order } as OrderBy);
    return this;
  }

和上边不同的是,orderBy可以进行叠加,多次调用增加排序条件

2.2.4 groupBy
  groupBy(name: string): DataBase {
    if (!this.form) throw new Error("none connect");
    if (!this.form.groupBy) {
      this.form.groupBy = [];
    }
    this.form.groupBy.push(name);
    return this;
  }

groupBy可以进行叠加

2.2.5 get

当我们调用get,才真正发送请求,我这里仅把结果返回进行查看

const sleep = async (ms: number) =>
  new Promise((resolve) => {
    setTimeout(() => {
      resolve(1);
    }, ms);
  });
async get() {
    await sleep(500);
    const form = { ...this.form };
    this.clear();
    return { code: DBcode.success, source: form } as DataBaseRes;
  }

3 测试

我们调用上边的get的话:

const demo = async () => {
  const db = new DataBase();
  const res = await db
    .collection("UserInfo")
    .where({
      name: "BugYalu",
    })
    .limit(1)
    .get();
  console.log(res);
};

打印结果如下

image-20211226235402080

当然我们也可以真的把get封装一下,那它就会像这样

image-20211226235704951
补一份总代码

import { axiosBase } from "./apis";

const sleep = async (ms: number) =>
  new Promise((resolve) => {
    setTimeout(() => {
      resolve(1);
    }, ms);
  });
enum DBcode {
  success,
  fail,
}
interface DataBaseRes {
  code: DBcode;
  source: any;
}

interface DataBaseInterface {
  form: null | DBForm;
  collection(name: string): DataBase;
  clear(): void;
  where(condition: WhereCondition): DataBase;
  limit(val: number): DataBase;
  orderBy(name: string, sort: OrderBySort): DataBase;
  skip(val: number): DataBase;
  groupBy(name: string): DataBase;
  get(): Promise<DataBaseRes>;
}
interface WhereCondition {
  [key: string]: any;
}
enum OrderBySort {
  asc,
  desc,
}
interface OrderBy {
  name: string;
  order: OrderBySort;
}
interface DBForm {
  orderBy?: Array<OrderBy>;
  where?: WhereCondition;
  collection: string;
  limit?: number;
  groupBy: Array<string>;
  skip?: number;
}
class DataBase implements DataBaseInterface {
  form: DBForm | null;
  constructor() {
    this.form = null;
  }
  clear() {
    this.form = null;
  }

  collection(name: string) {
    this.form = Object.create(null);
    this.form!.collection = name;
    return this;
  }

  where(condition: WhereCondition) {
    if (this.form?.where) {
      throw new Error("already existing[where]");
    }
    this.form!.where = condition;
    return this;
  }

  limit(val: number) {
    if (this.form?.limit) {
      throw new Error("already existing[limit]");
    }
    this.form!.limit = val;
    return this;
  }

  skip(val: number) {
    if (this.form?.skip) {
      throw new Error("already existing[skip]");
    }
    this.form!.skip = val;
    return this;
  }

  orderBy(name: string, order: OrderBySort) {
    if (!this.form) throw new Error("none connect");
    if (!this.form.orderBy) {
      this.form.orderBy = [];
    }
    this.form.orderBy.push({ name, order } as OrderBy);
    return this;
  }

  groupBy(name: string): DataBase {
    if (!this.form) throw new Error("none connect");
    if (!this.form.groupBy) {
      this.form.groupBy = [];
    }
    this.form.groupBy.push(name);
    return this;
  }

  async get() {
    await sleep(500);
    const form = { ...this.form };
    this.clear();
    axiosBase.post("/hhh", { ...form });
    return { code: DBcode.success, source: form } as DataBaseRes;
  }
}
export { DataBase };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值