0
点赞
收藏
分享

微信扫一扫

封装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 不太一样。

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

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

就这?

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

举报

相关推荐

0 条评论