封装webSQL(一)做个help先

首先,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 不太一样。

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

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

就这?

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Web SQL 首先呢,HTML5已经放弃了 Web SQL,这里做这个封装,主要是为了练手,另外是为了做在线演示...
    自然框架阅读 619评论 0 3
  • 关于Mongodb的全面总结 MongoDB的内部构造《MongoDB The Definitive Guide》...
    中v中阅读 32,016评论 2 89
  • 本文介绍本地数据存储的选型。简单总结一些查询到的关于本地数据存储的技术。 控制台展示前端存储 Chrome: 前端...
    谢大见阅读 9,130评论 1 8
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,366评论 11 349
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 126,028评论 2 7