ES6(六)用Class + Promise封装一下Web SQL

简介: 用Class + Promise封装一下Web SQL

Web SQL



首先呢,HTML5已经放弃了 Web SQL,这里做这个封装,主要是为了练手,另外是为了做在线演示。


后端一般都采用关系型数据库,有些关于sql语句的在线演示就需要弄个后端,但是成本比较高,那么如果能够用前端的websql模仿一下,是不是可以呢?


因为都是用sql语句,基础的操作方式还是相同的,介绍一下原理没啥问题,所以呢,并不是真的要在项目里面使用,对于websql目前初步的感受来说,挺麻烦的。。。


打开数据库



要说webSQL还真是简单,或者说是简陋,就是开库,事务,提交SQL语句,然后就没了,剩下的自由发挥吧。


那么还是简单的封装一下。


/**
 * webSQL 的封装,基于 promise 便于操作
 * * 建立数据库
 * * 封装sql实现增删改查
 */
export default class webSQLHelp {
  constructor (dbName, ver, description) { // constructor是一个构造方法,用来接收参数
    this.dbName = dbName // this代表的是实例对象
    this.ver = ver
    this.description = description
    this.db = window.openDatabase(this.dbName, this.ver, this.description, 2 * 1024 * 1024)
  }
  /**
   * 打开指定的webSQL数据库
   * @returns 数据库的实例
   */
  openDb () {
    return this.db
  }
  ...
}
复制代码


先体验一下ES6 的 class(不是TS的),果然和 function 没啥大的区别,初始化传入参数打开数据库,备用。 好像把数据库名称记录下来似乎也没啥大用。


建立表



然后用建表语句建立表,看了一下资料,似乎也不用设置字段的类型,那么就简单一点,根据对象的属性来建立一个表。


/**
   * 创建表
   * @param { string } tableName 表名
   * @param { object } columns 表的对象,比如{name:'jyk', age: 12}
   * @returns 成功或者失败
   */
  createTable (tableName, columns) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      // 记录字段名称,不设置类型了。
      const cols = []
      for (const key in columns) {
        cols.push(key)
      }
      const sql = `CREATE TABLE IF NOT EXISTS ${tableName}
        (ID INTEGER PRIMARY KEY ASC, ${cols.join(',')} )`
      console.log('createSQL:', sql)
      // 调用事务,建立表
      this.db.transaction((tx) => {
        tx.executeSql(sql, [], (tx, results) => {
          console.log(tx, results)
          resolve(results)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


用 Promise 代替回调的方式。传入表名和对象,然后创建建表的SQL,提交建表搞定。


这里想实现 那种 表名.insert()的形式,但是水平有限,没弄出来。


添加数据



/**
   * 插入数据
   * @param { string } tableName 表名
   * @param { object } object 保存的对象
   * @returns 新增的ID值
   */
  insert (tableName, object) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      // 记录字段名称
      const colNames = []
      // 记录字段对应的值
      const colValues = []
      // 记录字段对应的占位符合
      const cols = []
      // 变量对象,记录 key和 value
      for (const key in object) {
        colNames.push(key)
        // colValues.push('"' + object[key] + '"')
        colValues.push(object[key])
        cols.push('?')
      }
      const sql = `INSERT INTO ${tableName}
        ( ${colNames.join(',')} ) VALUES ( ${cols.join(',')} )`
      console.log('insertSQL:', sql)
      this.db.transaction((tx) => {
        tx.executeSql(sql, colValues, (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者
          resolve(results.insertId)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


还是传入表名和对象,然后生成 insert 的SQL语句,提交添加搞定。


修改数据



/**
   * 修改数据
   * @param { String } tableName 表名
   * @param { Object } object 要修改的对象值
   * @param { Number } idValue 修改依据,id 的值
   * @returns 修改影响的行数
   */
  update (tableName, object, idValue) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      // 记录字段名称
      const colNames = []
      // 记录字段对应的值
      const colValues = []
      // 变量对象,记录 key和 value
      for (const key in object) {
        colNames.push(key + '=? ')
        colValues.push(object[key])
      }
      // 加入查询条件
      colValues.push(idValue)
      const sql = `UPDATE ${tableName} SET ${colNames.join(',')} WHERE id=?`
      console.log('updateSQL:', sql)
      console.log('updateSQL2:', colValues)
      this.db.transaction((tx) => {
        tx.executeSql(sql, colValues, (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者 影响行数
          resolve(results.rowsAffected)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


一样,改改SQL就好。另外需要加一个where 的条件,否则就都删掉了。


删除数据



/**
   * 删除一条记录
   * @param { String } tableName 表名
   * @param { Number } idValue 删除依据
   * @returns 删除状态
   */
  delete (tableName, idValue) {
    const promise = new Promise((resolve, reject) => {
      console.log('this.db', this.db)
      const sql = `DELETE FROM ${tableName} WHERE id=?`
      console.log('deleteSQL:', sql)
      this.db.transaction((tx) => {
        tx.executeSql(sql, [idValue], (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者 影响行数
          resolve(results.rowsAffected)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


这个最简单了,delete一下就好。


查询数据



/**
   * 查询数据
   * @param { string } tableName 要查询的表名
   * @param { object } showCols 显示字段
   * @param { object } query 查询条件
   * @returns 查询结果,数组形式
   */
  select (tableName, showCols, query) {
    this.findKind = {
      // 字符串
      401: ' {col} = ? ',
      402: ' {col} <> ? ',
      403: ' {col} like ? ',
      404: ' {col} not like ? ',
      405: ' {col} like ? ', // 起始于
      406: ' {col} like ? ', // 结束于
      // 数字
      411: ' {col} = ? ',
      412: ' {col} <> ? ',
      413: ' {col} > ? ',
      414: ' {col} >= ? ',
      415: ' {col} < ? ',
      416: ' {col} <= ? ',
      417: ' {col} between ? and ? ',
      // 日期
      421: ' {col} = ? ',
      422: ' {col} <> ? ',
      423: ' {col} > ? ',
      424: ' {col} >= ? ',
      425: ' {col} < ? ',
      426: ' {col} <= ? ',
      427: ' {col} between ? and ? ',
      // 范围
      441: ' {col} in (?)'
    }
    const promise = new Promise((resolve, reject) => {
      const _whereCol = []
      const _whereValue = []
      for (const key in query) {
        const val = query[key]
        _whereCol.push(this.findKind[val[0]].replace('{col}', key))
        switch (val[0]) {
          case 403: // like
          case 404: // not like
            _whereValue.push('%' + val[1] + '%')
            break
          case 405: // like a%
            _whereValue.push(val[1] + '%')
            break
          case 406: // like %a
            _whereValue.push('%' + val[1])
            break
          case 417: // between 数字
          case 427: // between 日期
            _whereValue.push(...val[1])
            break
          case 441: // in
            _whereCol[_whereCol.length - 1] =
              _whereCol[_whereCol.length - 1]
                .replace('?', val[1].map(a => '?').join(','))
            _whereValue.push(...val[1])
            break
          default:
            _whereValue.push(val[1])
            break
        }
      }
      if (_whereCol.length === 0) {
        _whereCol.push(' 1=1 ')
      }
      const sql = `SELECT * FROM ${tableName} WHERE ${_whereCol.join(' and ')}`
      console.log('selectSQL1:', sql)
      console.log('selectSQL2:', _whereValue)
      this.db.transaction((tx) => {
        tx.executeSql(sql, _whereValue, (tx, results) => {
          console.log(tx, results)
          // 成功了,返回给调用者 影响行数
          resolve(results.rows)
        }, (tx, err) => {
          console.log(tx, err)
          reject(err)
        })
      })
    })
    return promise
  }
复制代码


好吧,其实主要就是为了这个查询,这不在做查询控件么,演示的时候,还是有个数据变化来得更生动一些,但是有没钱弄后端服务器。于是就用websql代替一下吧。


这里设置了一个查询结构,这个 select 就是把这个查询结构解析成SQL语句,然后交给数据库执行,看看查询效果。


使用方法



在vue环境下使用


import WebSqlHelp from '@/store-nf/websql-help.js'
export default {
  name: 'websql',
  components: {
  },
  setup (props, ctx) {
    const help = new WebSqlHelp('db-findtest', '1.0', '演示一下查询控件')
    console.log(help)
    const person = {
      name: 'jyk',
      age: 18,
      brithday: '1970-1-1',
      aa: {
        a1: 'a111',
        a2: 'a222'
      }
    }
    const sqlCreate = () => {
      // 依据 person 建立一个表
      help.createTable('person3', person).then(() => {
        // 往表里面加数据
        help.insert('person3', person).then((id) => {
          console.log('newId', id)
        })
      })
    }
    const zsgc = () => {
      // 修改指定的数据
      person.age = 111
      help.update('person3', person, 3).then((id) => {
        console.log('updateId', id)
      })
      // 删除指定的数据
      help.delete('person3', 4).then((id) => {
        console.log('deleteId', id)
      })
    }
    const dataList = reactive([])
    const sqlSelect = () => {
      // 查询数据
      help.select('person3', {}, {
        // id: [401, 2]
      }).then((data) => {
        console.log('select:', data)
        dataList.length = 0
        dataList.push(...data)
      })
    }
    return {
      sqlCreate,
      sqlSelect,
      dataList
    }
  }
}
复制代码


  • 嵌套对象


默认只支持单层属性,套娃是不支持的,直会存入 “[object Object]” 这个东东。 这里只是简单的演示,就不做转换了。


  • 多表关联


没考虑那么复杂,因为没打算演示这些复杂的操作,头疼。就简单粗暴的演示一下单表查询就好。 同理,分组统计这类的也不考虑。


总结



发现好多小问题,前端嘛,还是用 indexedDB 的好,用webSQL实在太不放心了,维护起来也感觉忒麻烦。


可以删除表,但是听说不能删除数据库?那难道只能等360清理?


相关文章
|
1月前
|
前端开发
理解 ES6 中的 Promise
【10月更文挑战第24天】ES6 中的 Promise 是一种用于处理异步操作的机制,它提供了一种更优雅、更可控的方式来处理异步任务的结果。Promise 可以看作是对异步操作结果的一种承诺,它可以处于三种不同的状态:Pending(等待中)、Fulfilled(已完成,即成功)和 Rejected(已拒绝,即失败)。
|
1月前
|
SQL 安全 前端开发
Web学习_SQL注入_联合查询注入
联合查询注入是一种强大的SQL注入攻击方式,攻击者可以通过 `UNION`语句合并多个查询的结果,从而获取敏感信息。防御SQL注入需要多层次的措施,包括使用预处理语句和参数化查询、输入验证和过滤、最小权限原则、隐藏错误信息以及使用Web应用防火墙。通过这些措施,可以有效地提高Web应用程序的安全性,防止SQL注入攻击。
52 2
|
2月前
|
前端开发 JavaScript 小程序
JavaScript的ES6中Promise的使用以及个人理解
JavaScript的ES6中Promise的使用以及个人理解
23 1
|
2月前
|
前端开发 Java
说说你对es6中promise的理解?
说说你对es6中promise的理解?
17 1
|
2月前
|
前端开发 Java
说说你对es6中promise的理解?
说说你对es6中promise的理解?
|
2月前
|
SQL
Web for Pentester SQL sql注入靶场
Web for Pentester SQL sql注入靶场
|
3月前
|
SQL 安全 数据库
惊!Python Web安全黑洞大曝光:SQL注入、XSS、CSRF,你中招了吗?
在数字化时代,Web应用的安全性至关重要。许多Python开发者在追求功能时,常忽视SQL注入、XSS和CSRF等安全威胁。本文将深入剖析这些风险并提供最佳实践:使用参数化查询预防SQL注入;通过HTML转义阻止XSS攻击;在表单中加入CSRF令牌增强安全性。遵循这些方法,可有效提升Web应用的安全防护水平,保护用户数据与隐私。安全需持续关注与改进,每个细节都至关重要。
142 5
|
3月前
|
前端开发 JavaScript
ES6新标准下JS异步编程Promise解读
ES6新标准下JS异步编程Promise解读
41 3
|
3月前
|
SQL 安全 数据库
深度揭秘:Python Web安全攻防战,SQL注入、XSS、CSRF一网打尽!
在Web开发领域,Python虽强大灵活,却也面临着SQL注入、XSS与CSRF等安全威胁。本文将剖析这些常见攻击手段,并提供示例代码,展示如何利用参数化查询、HTML转义及CSRF令牌等技术构建坚固防线,确保Python Web应用的安全性。安全之路永无止境,唯有不断改进方能应对挑战。
82 5
|
4月前
|
前端开发
手写实现ES6的Promise.all()和Promise.race()函数
这篇文章介绍了如何手写实现ES6的`Promise.all()`和`Promise.race()`函数,提供了实现这两个Promise聚合函数的详细代码示例,并展示了如何使用它们。
手写实现ES6的Promise.all()和Promise.race()函数
下一篇
DataWorks