Skip to content

Instantly share code, notes, and snippets.

@nakamura-to
Created August 1, 2012 07:38
Show Gist options
  • Save nakamura-to/3224648 to your computer and use it in GitHub Desktop.
Save nakamura-to/3224648 to your computer and use it in GitHub Desktop.
Cache-enabled Gateway for Metro Style Applicatoin
(function () {
/* */
/* EXAMPLE */
/* */
//var db = new KageDB({
// name: "db",
// version: 1,
// migration: {
// 1: function (ctx, next) {
// var db = ctx.db;
// db.createObjectStore("__cacheStatus", { keyPath: "id" });
// var person = db.createObjectStore("person", { autoIncrement: true });
// next();
// }
// }
//});
//
//var gateway = new Gateway({
// db: db,
// baseUrl: "http://localhost:49637/api"
//});
//
//gateway.get({
// path: "person/get",
// pkey: "name",
//}).then(function (data) {
// console.log(data);
//});
"use strict";
function Gateway(options) {
this.options = options || {};
}
Gateway.prototype.get = function get(options) {
var self = this;
options = this._mergeOptions(options);
var store = extractObjectStore();
var path = makePath();
return isCached().then(function (cached) {
if (cached) {
return getFromCache();
} else {
return getFromServer();
}
});
function extractObjectStore() {
var path = options.path;
var pos = path.indexOf("/");
if (pos > -1) {
return path.substr(0, pos);
}
return path;
}
function makePath() {
var path = options.path;
if (options.data) {
Object.keys(options.data).forEach(function (key, i) {
if (i === 0) {
path += "?";
} else {
path += "&";
}
var value = options.data[key];
if (value == null) {
value = "";
}
path = path + key + "=" + value;
});
}
return path;
}
function isCached() {
return new WinJS.Promise(function (c) {
if (options.cache) {
options.db.tx(["__cacheStatus"], function (tx, status) {
status.get(path, function (result) { c(!!result) });
});
} else {
c(false);
}
});
}
function getFromCache() {
return new WinJS.Promise(function (c) {
options.db.tx([store], function (tx, store) {
store.fetch({ filter: filter }, c);
function filter(row) {
return row.__cacheKeys.indexOf(path) > -1;
}
});
});
}
function getFromServer() {
return self._xhr("get", path, null, options).then(function (result) {
var data;
if (options.responseType === "json") {
data = JSON.parse(result.response);
}
// TODO handle other responseTypes
if (options.cache) {
return cache(data).then(function () {
return data;
});
}
return data;
});
}
function cache(data) {
return new WinJS.Promise(function (c) {
options.db.tx(["__cacheStatus", store], "readwrite", function (tx, status, store) {
status.put({ id: path }, function () {
var pkey = options.pkey;
var array = Array.isArray(data) ? data : [data];
var len = array;
store.openCursor(function (cursor) {
if (cursor) {
var row = cursor.value;
for (var i = 0; i < array.length; i++) {
var newRow = array[i];
if (row[pkey] == newRow[pkey]) {
row.__cacheKeys.push(path);
cursor.update(row);
break;
}
}
cursor.cont();
} else {
array.forEach(function (row) {
row.__cacheKeys = [path];
});
store.bulkPut(array, c);
}
});
});
});
});
}
};
Gateway.prototype.post = function post(options) {
options = this._mergeOptions(options);
// TODO
};
Gateway.prototype.put = function put(options) {
options = this._mergeOptions(options);
// TODO
};
Gateway.prototype.del = function del(options) {
options = this._mergeOptions(options);
// TODO
};
Gateway.prototype._mergeOptions = function _mergeOptions(options) {
options = options || {};
var result = {};
Object.keys(this.options).forEach(function (key) {
result[key] = this.options[key];
}, this);
Object.keys(options).forEach(function (key) {
result[key] = options[key];
});
// verify
if (result.baseUrl == null) throw new Error("`baseUrl` is required.");
if (result.db == null) throw new Error("`db` is required.");
if (result.path == null) throw new Error("`path` is required.");
if (result.pkey == null) throw new Error("`pkey` is required.");
// default settings
if (result.cache == null) result.cache = true;
if (result.responseType == null) result.responseType = "json";
if (result.user == null) user: result.user = "";
if (result.password == null) result.password = "";
if (result.customRequestInitializer == null) result.customRequestInitializer = function () { };
return result;
};
Gateway.prototype._xhr = function (type, path, data, options) {
var url;
if (options.baseUrl.charAt(options.baseUrl.length - 1) === "/") {
url = options.baseUrl + path;
} else {
url = options.baseUrl + "/" + path;
}
var xhrOptions = {
type: type,
url: url,
data: data,
headers: { "Content-type": "application/json; charset=utf-8" },
responseType: options.responseType,
user: options.user || "",
password: options.password || "",
customRequestInitializer: options.customRequestInitializer || function () { }
};
return WinJS.xhr(xhrOptions);
}
// TODO
window.Gateway = Gateway;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment