封装webSQL(一)做个help先

作者: 自然框架 | 来源:发表于2021-07-22 19:33 被阅读0次

首先,webSQL并不在HTML的标准内,这里封装 webSQL 主要是为了后端的 MySQL。

因为想在前端做一个缓存机制,实现一些类似于 git 的功能,这个以后在细说,总之,想按照后端封装MySQL的方式,封装一下webSQL,实现接口、参数、返回值基本一致,或者类似。

SQL 的操作都很基础,核心就是两件事情:打开连接,传递SQL,得到结果。

我们先封装一个help。

/**
 * 基于 promise 封装 webSQL 的基本操作
 * * 创建数据库连接
 * * 提交SQL给数据库执行,得到返回结果
 * * 共用函数
 * * info 结构:
 * * * dbName: 'test',  // 数据库名称
 * * * ver: '1', // 版本,很重要
 * * * size: '2', // 大小,自动 * 1024 * 1024
 * * * description: '数据库描述'
 */
export default class MySQLHelp {
  constructor (info) {
    // 创建普通连接的参数
    this._info = {
      dbName: info.dbName,
      ver: info.ver,
      size: info.size,
      description: info.infodescription
    }
    // 打开数据库
    this.db = window.openDatabase(
      this._info.dbName,
      this._info.ver,
      this._info.description,
      this._info.size * 1024 * 1024)
    
    console.log(` ★ 初始化!${info.dbName}`)
  }
 

  /**
   * 开启一个事务,Promise 的方式
   * @returns Promise 形式
   */
  begin() {
    const myPromise = new Promise((resolve, reject) => {
      // 开启一个事务。
      console.log('★ 开启事务,promise 模式')
      this.db.transaction(
        (tx) => { resolve(tx) },
        (tx, err) => {reject(err)}
      )
    })
    return myPromise
  }
  
  /**
   * 直接运行SQL
   * @param { string } sql SQL语句
   * @param { arror } param 参数
   * @returns promise
   */
   query (sql, param=[], cn = null) {
    const promise1 = new Promise((resolve, reject) => {
      const _query = (_cn) => {
        _cn.executeSql(
          sql, param,
          (tx, results) => { resolve(results) },
          (tx, err) => {
            console.log('query - sql:', sql, param, tx, err)
            reject(err)
            return true // 回滚
          }
        )
      }
      if (cn === null) {
        this.begin().then((__cn) => {
          _query(__cn)
        })
      } else {
        _query(cn)
      }
    })
    return promise1
  }
}

  • window.openDatabase
    创建并且打开一个数据库

  • begin() db.transaction
    开启一个事务。似乎好像必须先开始事务,然后才可以访问数据库。所以把这个拿出来单独封装一个函数,主要是为了能够连续使用事务。

  • query(sql, param=[], cn = null)
    把 SQL 提交给数据库执行(含参数),然后等待返回结果。
    这里写的有点绕,主要是想兼容是否使用事务的两种用法。

使用方式


// 测试webSQL的访问
import webSQL from '../../packages/nf-ws-indexeddb/help.js'

const info = {
  dbName: 'test_websqldb',
  ver: '1',
  size: 2,
  description: '测试一下新的封装方式'
}
const help = new webSQL(info)

const tableName = 't_table'
const cols = ['a','b']
const sql = `CREATE TABLE IF NOT EXISTS ${tableName} (ID INTEGER PRIMARY KEY ASC, ${cols.join(',')} )`

help.query(sql, []).then((res) => {
  console.log('建表完毕', res)

  // const sql2 = 'insert into t_table (id,a,b) values (0,?,?)'
  const sql2 = 'insert into t_table (a,b) values (?,?)'
  const param = ['111','ddd']
  help.query(sql2, param).then((res) => {
    console.log('添加数据:', res)
  })
})

  • 建立对象
    首先 import 进来,然 new 一个对象出来。

  • 建表
    后端的MySQL可以在上线前先把数据库准备好,但是前端的webSQL就得每次运行前先检查是否已经有表,所以第一步是建立一个表。
    webSQL 比较宽松,似乎没有对字段类型进行检查,所以建表的时候也就不去定义字段类型了。

  • 添加数据
    再做一个添加数据的测试。

其他用法

  • 连续用法

const tableName = 't_table'
const cols = ['a','b']
const sql = `CREATE TABLE IF NOT EXISTS ${tableName} (ID INTEGER PRIMARY KEY ASC, ${cols.join(',')} )`

help.query(sql, []).then((res) => {
  console.log('建表完毕', res)
})

const sql2 = 'insert into t_table (a,b) values (?,?)'
const param = ['222','eee']
help.query(sql2, param).then((res) => {
  console.log('添加数据:', res)
})

因为 js 是单线程的,所以其实我们可以依次写代码,而不必把下一条放在回调函数里面。

依次执行

其实这种用法开启了两次事务。

  • 事务用法

help.begin().then((cn) => {
  help.query(sql, [], cn).then((res) => {
    console.log('建表完毕', res)
  })
  help.query(sql2, param, cn).then((res) => {
    console.log('添加数据:', res)
  })
})

我们可以显性开始事务,这样就不必多次开启事务了。

开启事务

不用提交事务?

事务好像是默认提交的。
如果要回滚事务的话,需要第四个参数(最后一个回调函数) return true。

添加的数据

两个事务同时写会如何?

// 事务一
help.begin().then((cn) => {
  param[1] = '11'
  help.query(sql2, param, cn).then((res) => {
    console.log('添加数据:', res)
  })
  param[1] = '22'
  help.query(sql2, param, cn).then((res) => {
    console.log('添加数据:', res)
  })
  param[1] = '33'
  help.query('', param, cn).then((res) => { // 触发回滚
    console.log('添加数据:', res)
  })
})

// 事务二
help.begin().then((cn) => {
  param[1] = '66'
  help.query(sql2, param, cn).then((res) => {
    console.log('添加数据:', res)
  })
  param[1] = '77'
  help.query(sql2, param, cn).then((res) => {
    console.log('添加数据:', res)
  })
  param[1] = '88'
  help.query(sql2, param, cn).then((res) => {
    console.log('添加数据:', res)
  })
})

测试了一下,感觉和后端的 node + MySQL 不太一样。

前端并没有出现交替添加的情况,而是依次添加。可能是因为,都是单线程的原因吧。

事务也可以独立回滚,不会影响另一个事务。

就这?

当然不是,这只是最基础的操作,后面更精彩。。。

相关文章

  • 封装webSQL(一)做个help先

    首先,webSQL并不在HTML的标准内,这里封装 webSQL 主要是为了后端的 MySQL。 因为想在前端做一...

  • 封装 MySQL(一)做个help先

    Node.js 环境里面访问 MySQL 的默认方式,采用了古老的回调方式,这样很容易产生回调地狱。那么如何避免呢...

  • 封装 indexedDB(一)做个help先

    不知道大家有没有发现,我封装了后端的 MySQL,前端的 webSQL,而现在又要对 indexedDB 下手了。...

  • 封装webSQL(五)封装 get

    获取记录,看似简单,其实也可以分为很多情况。 根据ID获取一条记录 根据查询条件获取记录 分页获取记录 各种统计查...

  • 封装webSQL(八)封装 “编辑”

    一般的需求是,一个表单,要么是添加状态,要么是修改状态,可以实现明确需求。 但是有的时候却不能实现明确是添加还是修...

  • 封装webSQL(二)封装 insert into

    永远不要手撸SQL SQL要手写吗?当然不是,我们可以根据功能进行各种封装,比如先封装一个添加 model 用的S...

  • 封装webSQL(三)封装 update

    修改语句 这里的修改,特指通过主键ID,修改记录(model),其他修改方式再封装其他函数。 这个更简单,只是多了...

  • 封装webSQL(四)封装 delete

    删除语句 一般项目都有两种删除方式,一种是物理删除,一种是逻辑删除。物理删除就是用 delete 语句,把记录从数...

  • 封装webSQL(六)封装 统计和查询

    下一步要做什么呢?要为分页做准备,首先实现统计和查询的功能。 sql 封装 统计功能比较简单,只是需要处理一下查询...

  • 封装webSQL(七)封装 分页和查询

    虽然现在分页的方式多种多样,不像以前只能按页翻,但是基础原理还是一样的。 webSQL的分页比较简单(不考虑性能的...

网友评论

    本文标题:封装webSQL(一)做个help先

    本文链接:https://www.haomeiwen.com/subject/sokymltx.html