前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用NW.js构建跨平台桌面应用(4)-数据持久化

用NW.js构建跨平台桌面应用(4)-数据持久化

作者头像
江米小枣
发布2020-06-15 14:59:07
1.9K0
发布2020-06-15 14:59:07
举报
文章被收录于专栏:云前端云前端

与web开发中主要将数据保存在服务器端不同(cookie中仅保存极少量信息且会过期),数据持久化(Data Persistence)是本地应用开发中的常见需求,通俗的讲就是将瞬时数据(比如内存中的数据,断电即失效)保存为持久数据(比如写入数据库中长久保存); 由于NW.js的特性,可供选择的本地持久化方案非常丰富,既可以依赖于Node.js直接使用NeDB、LowDB等第三方数据库方案,也可以使用HTML5及其相关标准中提供的WebSQL、WebStorage、IndexedDB等方案,甚至直接将简单的数据保存到本地文件中

[I]. 直接存储数据到本地文件

正如之前的文章提到过的,NW.js提供了App.dataPath来访问系统的应用数据目录, 可以利用其方便的存储应用配置文件等

不同平台上的具体指向:

  • Win: $LOCALAPPDATA%/
  • Linux: ~/.config/
  • Mac: ~/Library/Application Support/
代码语言:javascript
复制
var fs = require('fs');
var path = require('path');function saveSettings (settings, callback) {
   var file = 'my-settings-file.json';
   var filePath = path.join(nw.App.dataPath, file);
   fs.writeFile(filePath, settings, function (err) {
       if (err) {
           console.warn(err.message);
           return;
       } else if (callback) {
           callback();
       }
   });
}var mySettings = {
   "language": "zh-CN",
   "theme": "dark"
};saveSettings(mySettings, function () {
   console.log('Settings saved');
});

[II]. Web storage

Web storage 是浏览器中最简单的一种数据存储技术,可以暂时或永久的保存 key-value 数据;适合于简单且非密集的数据事务场景

2.1 基本规则

  • 每个domain最多5MB的存储限制
  • 同步调用,有可能阻塞主渲染进程
  • 直接读写磁盘,可能影响性能
  • 没有高级的索引和查询等
  • 只能用字符串存取数据,复杂数据和图片应分别用JSON和base64转码后存储
  • 可以在 DevTools->Application->Storage->Local Storage 标签页中查看已存储的数据

2.2 操作方法

代码语言:javascript
复制
//存数据
localStorage.setItem('myKey', myValue);//取数据, 无结果返回null
localStorage.getItem('myKey');
localStorage.myKey;
localStorage['myKey'];//删数据
localStorage.removeItem('myKey');
delete localStorage.myKey;
localStorage.clear();//存储数据时会触发事件(可用于监听其他页面是否修改了某个数据)
window.addEventListener('storage' e=>console.log(e.key, e.newValue));

2.3 基于localStorage的StoreDB

StoreDB(https://github.com/djyde/StoreDB) 是一个基于localStorage的本地储存库,通过模拟MongoDB的一些API和概念(如“集(collection)”和“文档(document)”),使你能使用 localStorage 储存复杂数据

代码语言:javascript
复制
//插入数据
storedb('players').insert({
   "name":"Randy",
   "sex":"male",
   "score":20
},function(err,result){
 if(!err){
   //do sth...
 } else //do sth...
})//更新数据
storedb('players').update(
   {"name":"Randy"},
   {"$inc":{"score":"10"}
},function(err){
 if(!err){
   //do sth...
 } else //do sth...
})//查找数据
storedb('players').find({
   "name":"Randy"
},function(err,result){
 if(!err){
   //use result to do sth...
 } else //do sth...
})

[III]. Web SQL 数据库

  • Web SQL 是一个基于 SQLite 的数据库规范,使得在浏览器端使用 SQL 语言(如select, insert, update, delete, joins, inner selects等)变得简便易行 --- 这也是其最大的优点
  • Web SQL Database API 实际上未包含在 HTML 5 规范之中,它是一个独立的规范
  • 其 API 有同步的,也有异步的, 同步版本的 API 只在工作线程(Worker Threads)上有用,由于并不是所有的浏览器都支持工作线程,一般情况下,都会使用异步 API
  • 基本没有容量限制
  • 虽然 W3C 官方已经声明不再维护 Web SQL Database 规范,但由于其广泛的实现程度,了解这些 API 对 Web 开发还是非常有必要的

3.1 基本概念

  • SQL语句(SQL statement): 一条SQL查询语句
  • 事务(transaction): 管理并顺序执行若干条SQL语句的容器,可以嵌套
  • 错误回调:每条 SQL statement 及其所处的 transaction 都有各自的错误回调,用于精细或集约的捕获错误并引发回滚
  • 回滚(roll back):错误发生时撤销单条语句或整个事务的操作
  • 可以在 DevTools->Application->Storage->Web SQL 标签页中查看已存储的数据

3.2 常用方法

  • openDatabase(): 新建数据库对象或打开已有的
  • transaction(): 执行一个事务并在错误发生时回滚
  • executeSql(): 执行SQL语句
代码语言:javascript
复制
//初始化一个数据库
var db = openDatabase(
   'myDB', //数据库名
   '1.0', //版本号
   'My Database', //显示名
   2 * 1024 * 1024, //容量
   db=> console.log() //成功回调
);//执行一个事务
db.transaction(t=>{
   //创建表
   let sql1 = "CREATE TABLE IF NOT EXISTS articles (id INTEGER PRIMARY KEY, title TEXT, content TEXT)";
   t.executeSql(sql1);
   //插入一条数据
   let data1 = ['标题1', '内容1'];
   let sql2 = "INSERT INTO articles(title, content) VALUES (?, ?)";
   t.executeSql(sql2, data1);
   
   //取数据
   db.transaction(t=>{
       t.executeSql(
           "SELECT * FROM articles",
           [],
           (transaction, resultSet)=> {
               let
                   data = []
                   ,row
                   ,rowNum = resultSet.rows.length
               ;
               for (let i = 0; i<rowNum; i++) {
                   row = resultSet.rows.item(i);
                   data.push(row);
               }
               console.log(data);
           }
       );
   });
   
   //向一个假定并不存在的表里插入数据,引发错误
   t.executeSql(
       "INSERT INTO logs(message) VALUES (?)",
       ["我是一条日志"],
       function sqlStatementCallback(transaction, resultSet) {},
       function sqlStatementErrorCallback(transaction, err) {
           //处理err
           //该条语句被回滚,如果有后续语句继续执行
           return false; //如果返回true,则会传递到事务的errorCallback
                       //,并引发整个事务的回滚
       }
   );
}, sqlError=> {
   console.warn(sqlError.message);
});

[IV]. IndexedDB

  • 存储 key-value 数据的事务型 NoSQL 非关系型数据库系统
  • 可以存储复杂的javascript对象,并用一个或多个索引查询
  • 基本没有容量限制
  • 所有操作都是异步的

4.1 基本概念

  • 数据库: 由 indexedDB.open(name, ver) 方法打开,返回一个IDBDatabase接口格式的异步请求对象
  • ObjectStore: 相当于关系型数据库中的数据库表table,实现IDBObjectStore接口
  • 事务(transaction): 所有ObjectStore的读写操作都借由事务完成
  • 可以在 DevTools->Application->Storage->IndexedDB 标签页中查看已存储的数据

4.2 代码示例

代码语言:javascript
复制
var
   dbName = 'DBName'
   ,dbVer = 1
   ,openDbRequest = indexedDB.deleteDatabase(dbName) && indexedDB.open(dbName, dbVer)
;
openDbRequest.onerror = e=>console.warn(e);
openDbRequest.onsuccess = e=>{
   let db = e.target.result;
   console.log('数据库建立成功:', db.version);
};
openDbRequest.onupgradeneeded = e=> {
   let db = e.target.result;
   console.log(e);   let
       storeName = 'personsStore'
       ,storeOptions = {
           keyPath: 'id',
           autoIncrement: true
       }
   ;   // if (db.objectStoreNames.contains(storeName)) {
   //  console.log('删除了旧数据库');
   //  db.deleteObjectStore(storeName);
   // }
   let store = db.createObjectStore(storeName, storeOptions);
   store.createIndex('by_name', 'name', {unique: false});
   store.createIndex('by_age', 'age', {unique: false});   setTimeout(function() {
       let
           ts = db.transaction(['personsStore'], 'readwrite')
           ,persons = ts.objectStore('personsStore')
       ;
       persons.add({
           name: '小红',
           age: 30
       });
       persons.add({
           name: '小明',
           age: 28
       }).onsuccess = function() {
           var key = this.result;
           alert(key);           persons.index('by_age').getAll().onsuccess =
               e=>console.log('index by_age', e.target.result);
           persons.get(key).onsuccess =
               e=>console.log('get 2', e.target.result);
       };
   }, 2000);
};

4.3 完整接口文档

https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API

4.4 第三方封装实现

  • Dexie: http://dexie.org/
代码语言:javascript
复制
var db = new Dexie("friend_database");
db.version(1).stores({
  friends: 'name,shoeSize'
});
db.friends.put({name: "Nicolas", shoeSize: 8}).then (function(){
  return db.friends.get('Nicolas');
}).then(function (friend) {
  alert ("Nicolas has shoe size " + friend.shoeSize);
}).catch(function(error) {
 alert ("Ooops: " + error);
});
  • PouchDB: https://pouchdb.com/
代码语言:javascript
复制
db.get('mittens').then(function (doc) {
  // okay, doc contains our document
}).catch(function (err) {
  // oh noes! we got an error
});

db.allDocs({include_docs: true}).then(res => {
    console.log(JSON.stringify(res))
});

db.get('mittens').then(function (doc) {
  return db.remove(doc);
});
  • https://github.com/nwjs/nw.js/wiki/Save-persistent-data-in-app
  • http://www.ccydesign.com/websql-amd-indexdb/
  • https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API
  • https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDBAPI/UsingIndexedDB
  • http://www.ibm.com/developerworks/library/wa-indexeddb/index.html
  • http://blog.csdn.net/cainiaokan/article/details/29366105
  • https://www.w3.org/TR/IndexedDB/#dfn-multientry
  • http://web.jobbole.com/81793/
  • http://www.csdn.net/article/2012-10-12/2810660-NoSQL-MongoDB-HBase
  • http://baike.baidu.com/item/NoSQL
  • http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html
  • http://www.cnblogs.com/dolphinX/p/3415761.html

* 原创文章转载请注明出处

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • [I]. 直接存储数据到本地文件
  • [II]. Web storage
    • 2.1 基本规则
      • 2.2 操作方法
        • 2.3 基于localStorage的StoreDB
        • [III]. Web SQL 数据库
          • 3.1 基本概念
            • 3.2 常用方法
            • [IV]. IndexedDB
              • 4.1 基本概念
                • 4.2 代码示例
                  • 4.3 完整接口文档
                    • 4.4 第三方封装实现
                    相关产品与服务
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档