Skip to content

Instantly share code, notes, and snippets.

@nolanlawson
Last active September 17, 2018 20:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nolanlawson/3e096160b848689f1058 to your computer and use it in GitHub Desktop.
Save nolanlawson/3e096160b848689f1058 to your computer and use it in GitHub Desktop.
Keep an in-memory array in sync with a PouchDB
<html>
<head>
<title>Reactive PouchDB demo</title>
<style>
h1, p, ul, li, button {
font-family: Helvetica, Arial, sans-serif;
}
button {
font-size: 16px;
padding: 10px;
cursor: pointer;
}
body {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
li {
list-style: none;
}
</style>
</head>
<body>
<h1>My list of docs</h1>
<div>
<button type="button" onclick="insertRandomDoc()">Add a doc</button>
<button type="button" onclick="updateRandomDoc()">Update a doc</button>
<button type="button" onclick="deleteRandomDoc()">Remove a doc</button>
</div>
<ul id="the-list"></ul>
<script src="//cdn.jsdelivr.net/pouchdb/latest/pouchdb.js"></script>
<script src="script.js"></script>
</body>
</html>
'use strict';
// this array will always be kept up-to-date with PouchDB
var docs = [];
var db = new PouchDB('somedb');
function binarySearch(arr, docId) {
var low = 0, high = arr.length, mid;
while (low < high) {
mid = (low + high) >>> 1; // faster version of Math.floor((low + high) / 2)
arr[mid]._id < docId ? low = mid + 1 : high = mid
}
return low;
}
function onDeleted(id) {
var index = binarySearch(docs, id);
var doc = docs[index];
if (doc && doc._id === id) {
docs.splice(index, 1);
}
}
function onUpdatedOrInserted(newDoc) {
var index = binarySearch(docs, newDoc._id);
var doc = docs[index];
if (doc && doc._id === newDoc._id) { // update
docs[index] = newDoc;
} else { // insert
docs.splice(index, 0, newDoc);
}
}
function fetchInitialDocs() {
return db.allDocs({include_docs: true}).then(function (res) {
docs = res.rows.map(function (row) { return row.doc; });
renderDocs();
});
}
function reactToChanges() {
db.changes({live: true, since: 'now', include_docs: true}).on('change', function (change) {
if (change.deleted) {
// change.id holds the deleted id
onDeleted(change.id);
} else { // updated/inserted
// change.doc holds the new doc
onUpdatedOrInserted(change.doc);
}
renderDocs();
}).on('error', console.log.bind(console));
}
function renderDocs() {
// this is a naive way to render documents. presumably
// your framework of choice (React, Angular, etc.) would have
// a more efficient way of doing this.
var ul = document.getElementById('the-list');
ul.innerHTML = docs.map(function (doc) {
return '<li><pre>' + JSON.stringify(doc, undefined, ' ') + '</pre></li>'
}).join('');
}
function insertRandomDoc() {
db.put({_id: Date.now().toString()}).catch(console.log.bind(console));
}
function updateRandomDoc() {
if (!docs.length) {
return;
}
var randomDoc = docs[Math.floor(Math.random() * docs.length)];
db.get(randomDoc._id).then(function (doc) {
if (!doc.updatedCount) {
doc.updatedCount = 0;
}
doc.updatedCount++;
return db.put(doc);
}).catch(console.log.bind(console));
}
function deleteRandomDoc() {
if (!docs.length) {
return;
}
var randomDoc = docs[Math.floor(Math.random() * docs.length)];
db.get(randomDoc._id).then(function (doc) {
return db.remove(doc);
}).catch(console.log.bind(console));
}
fetchInitialDocs().then(reactToChanges).catch(console.log.bind(console));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment