Browse files

Refactor & fixes.

- Got rid of old promise-based callbacks.
- Tightened some of the code up.
- Fixed an issue with save(), where it would save twice.
  • Loading branch information...
1 parent 8d3fd1f commit 59694c267c7d421134fda26a256388487af53c2c cloudhead committed Aug 11, 2010
Showing with 66 additions and 98 deletions.
  1. +66 −98 lib/cradle.js
View
164 lib/cradle.js
@@ -115,23 +115,17 @@ cradle.Connection.prototype.rawRequest = function (method, path, options, data,
// This is the entry point for all requests to CouchDB, at this point,
// the database name has been embed in the url, by one of the wrappers.
//
-cradle.Connection.prototype.request = function (method, path, options, data, headers) {
- var promise = new(events.EventEmitter), request, that = this, emitError = false;
+cradle.Connection.prototype.request = function (method, path, /* [options], [data], [headers] */ callback) {
+ var request, that = this, args = Array.prototype.slice.call(arguments, 2);
- promise.addCallback = function (callback) {
- if (callback) {
- this.addListener("done", callback);
- }
- return this;
- };
- promise.addListener('newListener', function (event, listener) {
- if (event === 'error') {
- emitError = true;
- }
- });
+ if (typeof(callback = args.pop()) !== 'function') {
+ args.push(callback);
+ callback = function () {};
+ }
- // HTTP Headers
- headers = cradle.merge({ host: this.host }, headers || {});
+ var options = args.shift() || {},
+ data = args.shift() || null,
+ headers = cradle.merge({ host: this.host }, args.shift() || {});
//
// Handle POST/PUT data. We also convert functions to strings,
@@ -144,7 +138,7 @@ cradle.Connection.prototype.request = function (method, path, options, data, hea
} else { return val }
});
headers["Content-Length"] = data.length;
- headers["Content-Type"] = "application/json";
+ headers["Content-Type"] = "application/json";
}
request = this.rawRequest(method, path, options, data, headers);
@@ -154,20 +148,19 @@ cradle.Connection.prototype.request = function (method, path, options, data, hea
// dispatch the request.
//
request.addListener('response', function (res) {
- var body = '';
+ var body = [];
res.setEncoding('utf8');
res.addListener('data', function (chunk) {
- body += (chunk || '');
+ chunk && body.push(chunk);
}).addListener('end', function () {
var obj, response;
if (method === 'HEAD') {
- promise.emit("done", null, res.headers, res.statusCode);
- promise.emit("success", res.headers, res.statusCode);
+ callback(null, res.headers, res.statusCode);
} else {
- try { obj = JSON.parse(body) }
- catch (e) { return promise.emitError(e) }
+ try { obj = JSON.parse(body.join('')) }
+ catch (e) { return callback(e) }
// If the `raw` option was set, we return the parsed
// body as-is. If not, we wrap it in a `Response` object.
@@ -176,19 +169,10 @@ cradle.Connection.prototype.request = function (method, path, options, data, hea
} else {
response = new(cradle.Response)(obj, res);
}
-
- promise.emit("done", (response.error && response.json) || null, response);
-
- if (response.error && emitError) {
- promise.emit("error", response.error);
- } else {
- promise.emit("success", response);
- }
+ callback((response.error && response.json) || null, response);
}
});
});
-
- return promise;
};
//
@@ -253,30 +237,22 @@ cradle.Connection.prototype.database = function (name) {
// A wrapper around `Connection.request`,
// which prepends the database name.
- query: function (method, path, options, data, headers) {
- return that.request(
- method, [name, path].join('/'), options, data, headers
- );
+ query: function (method, path /* [options], [data], [headers], [callback] */) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ that.request.apply(that, [method, [name, path].join('/')].concat(args));
},
- exists: function () {
- var promise = new(events.EventEmitter),
- args = new(Args)(arguments);
-
- this.query('GET', '/').addCallback(function (err, res) {
+ exists: function (callback) {
+ this.query('GET', '/', function (err, res) {
if (err) {
if (res.headers.status === 404) {
- args.callback(null, false);
- promise.emit("success", false);
+ callback(null, false);
} else {
- args.callback(err, res);
- promise.emit("error", res);
+ callback(err, res);
}
} else {
- args.callback(null, true);
- promise.emit("success", true);
+ callback(null, true);
}
});
- return promise;
},
// Fetch either a single document from the database, or cache,
@@ -287,16 +263,16 @@ cradle.Connection.prototype.database = function (name) {
args = new(Args)(arguments);
if (Array.isArray(id)) { // Bulk GET
- return this.query('POST', '/_all_docs', { include_docs: true }, { keys: id })
- .addCallback(function (err, res) { args.callback(err, res) });
+ this.query('POST', '/_all_docs', { include_docs: true }, { keys: id },
+ function (err, res) { args.callback(err, res) });
} else {
if (rev && args.length === 2) {
- if (typeof(rev) === 'string') { options = {rev: rev} }
+ if (typeof(rev) === 'string') { options = { rev: rev } }
else if (typeof(rev) === 'object') { options = rev }
} else if (this.cache.has(id)) {
return args.callback(null, this.cache.get(id));
}
- return this.query('GET', id, options).addCallback(function (err, res) {
+ this.query('GET', id, options, function (err, res) {
if (! err) that.cache.save(res.id, res.json);
args.callback(err, res);
});
@@ -320,24 +296,23 @@ cradle.Connection.prototype.database = function (name) {
} else {
throw new(Error)("Couldn't save without a _rev");
}
+ this.insert(doc, args.callback);
} else {
this.insert.apply(arguments);
}
- return this.insert(doc, args.callback);
},
- put: function (id, doc) {
- var cache = this.cache, args = new(Args)(arguments);
+ put: function (id, doc, callback) {
+ var cache = this.cache;
if (typeof(id) !== 'string') { throw new(TypeError)("id must be a string") }
- return this.query('PUT', id, null, doc).addCallback(function (e, res) {
- if (! e) cache.save(id, cradle.merge({}, doc, { _rev: res.rev }));
- args.callback(e, res);
+ this.query('PUT', id, null, doc, function (e, res) {
+ if (! e) { cache.save(id, cradle.merge({}, doc, { _rev: res.rev })) }
+ callback && callback(e, res);
});
},
- head: function (id) {
- var args = new(Args)(arguments);
- return this.query('HEAD', id, null).addCallback(args.callback);
+ head: function (id, callback) {
+ this.query('HEAD', id, null, callback);
},
insert: function (/* [id], doc, ... */) {
@@ -353,16 +328,16 @@ cradle.Connection.prototype.database = function (name) {
} else {
doc = args.last;
}
- return this.query('PUT', id, null, doc).addCallback(writeThrough);
+ this.query('PUT', id, null, doc, writeThrough);
// PUT or POST a single document
} else if (args.length === 1 && !Array.isArray(args.first)) {
doc = args.first;
id = doc._id;
if (id) {
- return this.query('PUT', id, null, doc).addCallback(writeThrough);
+ this.query('PUT', id, null, doc, writeThrough);
} else {
- return this.query('POST', '/', null, doc).addCallback(writeThrough);
+ this.query('POST', '/', null, doc, writeThrough);
}
// Bulk insert
@@ -373,14 +348,13 @@ cradle.Connection.prototype.database = function (name) {
} else {
doc = {docs: args.all};
}
- return this.query('POST', '/_bulk_docs', {}, doc)
- .addCallback(function (err, res) {
+ this.query('POST', '/_bulk_docs', {}, doc, function (err, res) {
args.callback(err, res);
});
}
function writeThrough(err, res) {
- if (! err) that.cache.save(id, cradle.merge({}, doc, { _rev: res.rev }));
+ if (! err) { that.cache.save(id, cradle.merge({}, doc, { _rev: res.rev })) }
args.callback(err, res);
}
},
@@ -392,7 +366,7 @@ cradle.Connection.prototype.database = function (name) {
if (arguments.length > 1) {
throw new(Error)("destroy() doesn't take any additional arguments");
} else {
- return this.query('DELETE', '/').addCallback(callback);
+ this.query('DELETE', '/', callback);
}
},
@@ -404,33 +378,33 @@ cradle.Connection.prototype.database = function (name) {
if (typeof(rev) !== 'string') {
if (doc = this.cache.get(id)) { rev = doc._rev }
- else { throw new(Error)("rev needs to be supplied") }
+ else { throw new(Error)("rev needs to be supplied") }
}
- return this.query('DELETE', id, {rev: rev})
- .addCallback(function (err, res) {
- if (! err) that.cache.purge(id);
+ this.query('DELETE', id, {rev: rev}, function (err, res) {
+ if (! err) { that.cache.purge(id) }
args.callback(err, res);
});
},
- create: function (c) {
- return this.query('PUT', '/').addCallback(c);
+ create: function (callback) {
+ this.query('PUT', '/', callback);
},
- info: function (c) {
- return this.query('GET', '/').addCallback(c);
+ info: function (callback) {
+ this.query('GET', '/', callback);
},
- all: function (options) {
- return this.query('GET', '/_all_docs', typeof(options) === 'object' ? options : {})
- .addCallback(Args.last(arguments));
+ all: function (options, callback) {
+ if (arguments.length === 1) { callback = options, options = {} }
+ this.query('GET', '/_all_docs', options, callback);
},
compact: function (design) {
- return this.query('POST', '/_compact' + (typeof(design) === 'string' ? '/' + design : ''))
- .addCallback(Args.last(arguments));
+ this.query('POST', '/_compact' + (typeof(design) === 'string' ? '/' + design : ''),
+ Args.last(arguments));
},
- viewCleanup: function (c) {
- return this.query('POST', '/_view_cleanup').addCallback(c);
+ viewCleanup: function (callback) {
+ this.query('POST', '/_view_cleanup', callback);
},
allBySeq: function (options) {
- return this.query('GET', '/_all_docs_by_seq', options).addCallback(c);
+ options = typeof(options) === 'object' ? options : {};
+ this.query('GET', '/_all_docs_by_seq', options, Args.last(arguments));
},
// Query a view, passing any options to the query string.
@@ -444,17 +418,14 @@ cradle.Connection.prototype.database = function (name) {
if (k in options) { options[k] = JSON.stringify(options[k]) }
});
}
- return this.query(
- 'GET', ['_design', path[0], '_view', path[1]].join('/'), options
- ).addCallback(args.callback);
+ this.query('GET', ['_design', path[0], '_view', path[1]].join('/'), options, args.callback);
},
push: function (doc) {},
saveAttachment: function (docOrId, attachmentName, contentType, dataOrStream) {
var rev, id, doc, pathname, headers = {}, response, body = '', resHeaders, error, db = this;
var args = new(Args)(arguments);
- var promise = new(events.EventEmitter);
if (typeof(docOrId) === 'string') {
id = docOrId;
@@ -487,10 +458,8 @@ cradle.Connection.prototype.database = function (name) {
revpos: new(Number)(response.rev.match(/^\d+/)[0])
};
}
- args.callback(response);
- promise.emit("success", response);
+ args.callback(null, response);
});
- return promise;
},
getAttachment: function(docId, attachmentName) {
@@ -506,24 +475,23 @@ cradle.Connection.prototype.database = function (name) {
// Wrapper functions for the server API
//
cradle.Connection.prototype.databases = function (c) {
- return this.request('GET', '/_all_dbs').addCallback(c);
+ this.request('GET', '/_all_dbs', c);
};
cradle.Connection.prototype.config = function (c) {
- return this.request('GET', '/_config').addCallback(c);
+ this.request('GET', '/_config', c);
};
cradle.Connection.prototype.info = function (c) {
- return this.request('GET', '/').addCallback(c);
+ this.request('GET', '/', c);
};
cradle.Connection.prototype.stats = function (c) {
- return this.request('GET', '/_stats').addCallback(c);
+ this.request('GET', '/_stats', c);
};
cradle.Connection.prototype.activeTasks = function (c) {
- return this.request('GET', '/_active_tasks').addCallback(c);
+ this.request('GET', '/_active_tasks', c);
};
cradle.Connection.prototype.uuids = function (count, callback) {
if (typeof(count) === 'function') { callback = count, count = null }
- return this.request('GET', '/_uuids', count ? {count: count} : {})
- .addCallback(callback);
+ this.request('GET', '/_uuids', count ? {count: count} : {}, callback);
};
cradle.merge = function (target) {

0 comments on commit 59694c2

Please sign in to comment.