是什么
它是一个利用Js和 HTML5 IndexedDB
实现的一个完全兼容 CouchDB
同步协议的家伙。
Q:能够说的再具体点么?
A:说白了,PouchDB
就是一个Js库,不过这个库是用来做本地数据存储的,尤其适合于需要基于浏览器的可离线使用的存储方案的移动应用。库本身压缩只有131KB,目前能做的基本任务有:数据库的创建、查询、复制与删除;文档(集)的创建、获取、更新及删除;查询数据库信息并监听数据库变化。更多信息,请看 PouchDB
怎么做
可以让你在浏览器里存储你的本地信息及数据等,然后通过 CouchDB
的同步协议将数据与远程服务器的数据进行同步。
Q:你不禁会问,CouchDB
的同步协议是啥?
A:简单的说,比如在移动终端中,CouchDB
的策略是在离线时将数据存在本地,在线后将数据与服务端进行同步。
怎么看
首先是它的爸比怎么看它呢,来看:
任何需要离线工作的 Web 应用(移动或其他),而且我相信大多数移动应用都需要离线工作。任何离线或“在云中”工作的应用都将面临可靠的数据同步的问题,它们都可能会使用 PouchDB。我能想到的显然的例子有待办工作列表和数据管理类的应用。
Harvey 补充,当将 PouchDB 与离线安装的 CouchDB 相比时:
CouchDB 在服务器上表现很棒,但是,它显然不可能在一个离线的 Web 应用中工作。PouchDB 是一个很小的可嵌入在浏览器中运行的 CouchDB,一旦在线,它又能与功能更为强大的 CouchDB 进行交互。
另外,PouchDB and jQuery's Promises 这篇文章讲到了了一点,它认为:PouchDB 几乎所有的API都是基于回调的,这样在嵌套复杂时,非常容易陷入 callback hell 之中,幸好有 Promise 这个非同步操作模式的神器存在,才免去了我们的后顾之忧。
不同的底层实现
PouchDB 访问不同的浏览器的底层存储引擎使用的是不同的API:
- INdexedDB:在 FF 和 Chrome 中
- WebSQL:在 Safari 和 Opera 中
- LevelDB:在 Node.js 中
开始你的Pouch
首先呢,我是下了官网上的那个 Todo-list 的demo,把里面的最重要的一个 app.js
跟着官网过了一遍,自己用 Node.js 的一个server跑,不用phthon的,其中遇到几个问题:
- Js代码中事件监听器设置中的回调函数通过
bind()
绑定参数这个不解,后来破解了,具体见 这里 - 另外就是Pouch的一些API,包括如何添加数据文件,这里面要注意,每增加一条 todo 事项,在 Pouch 中相当于生成一个具有唯一Id的 doc ,有多少条 todo 事项,就有多少个 doc ,这里 doc 可以理解为记录,这样你就能理解demo里面所提到的
showAll()
方法了
另外,有两个例子,一个是入门级的,很清晰地介绍了一个用 Pouch 建立 DB 的过程,详见 PouchDB Introduction from the beginning,另外,考虑上一节中讲到的用 jQuery 的promise来返回DB的用法。最后,是我重点要讲的这个:PouchDB: Beginning to Code
一些API
从0开始:可离线
// 貌似可行的方案1
var db = Pouch('localdb');
// 方案1优化,通过回调来初始化,判断Pouch模块是否能正常run
var db;
Pouch('localdb', function(err, database) {
if (err) {
console.log('Failed to create localdb');
} else {
db = database;
// Attention:从这(回调返回结果时)开始,我们就可以拿到初始化好的DB了
}
});
// 在这,我们倒不一定能够访问到 db,因为这时候异步执行的回调可能还没返回结果
从CouchDB Server创建:非离线
// 假设在本地我们搭了一个 CouchDB 的server,我们就可以从它来创建我们的PouchDB
var db;
Pouch('http://127.0.0.1:5984/testdb', function(err, database) {
if (err) {
console.log('Failed to initialise db');
} else {
db = database;
// 通过这一方法创建的是一个和后台数据库联系的DB,Pouch上的变化会马上传到Couch上
}
});
从replicate创建
// 复制
Pouch.replicate('http://127.0.0.1:5984/testdb', 'localdb', function(err, response) {
if (err) {
console.log("Failed to replicate CouchDB database to local copy");
}
// 注意这里第二个参数是 response 了,而不是 database 了
});
// 如果上面步骤不出错,我们复制成功,现在要做的就是去取那份copy
var db;
Pouch('localdb', function(err, database) {
if (err) {
console.log('Failed to get instance to localdb');
} else {
db = database;
}
});
获取所有DBs的列表
// 首先这个功能需要被开启才能用,而且需要在你复制或创建一个DB之前开启
Pouch.enableAllDbs = true;
// 获取所有DBs的列表,用 allDBs() 方法
Pouch.allDbs(function(err, response) {
if (err) {
console.log('Couldn't get list of databases');
} else {
console.log('List of databases:');
console.log(response);
}
});
获取一个已经存在的DB
// 很简单,用和创建DB同个API
db = Pouch(existingDbName);
获取DB的内容
// 你得判断DB是否是空的,比如如果是从0开始创建肯定是空的,如果是复制来的,或是从远端创建的肯定有东西
db.allDocs({include_docs: true}, function(err, docs) {
console.log(docs.rows);
});
往DB中写doc
// 主要有 put 和 post 两个方法,put 需要提供 _id,post 不需要;若id相同的doc又put了,视为更新
// 写 doc 也是异步的,以 post 为例
db.post({
type: 'test',
text: 'This is just a test'
}, function(err, response) {
if (err) {
console.log('Failed to write doc to DB');
} else {
console.log('Wrote successfully');
// 执行到这,doc 算是被写上了
}
});
// 在这,由于非同步执行的操作不一定完成,在这console.log()还不一定往DB中写上doc
获取特定的doc
// 有一个 _id 那么就可以去取它所指定的doc了,通过 get() 方法
db.get('known_doc_id', function(err, doc) {
if (err) {
console.log('Failed to get doc');
} else {
console.log(doc);
}
});
把本地修改推到远程
// 比如之前你是离线对本地DB进行了操作,现在又online了,要推回给远程这些change,
// 这时候还是replicate,只不过把 from 和 to 的位置换一下就可以了
Pouch.replicate('localdb', 'http://127.0.0.1:5984/testdb', function(err, response) {
if (err) {
console.log("Failed to replicate database back to CouchDB");
}
});
// 如果没有提示错误,那么change更新成功