Saturday, April 3, 2010

No More Promises in node.js

‹prev | My Chain | next›

Picking with a promised filled node.couch.js, I still need to remove said promises (as Mikeal Rogers puts it, it's been a month since node.couch.js was updated "and that's like a decade in the node.js world"). Promises were a pre 0.1.30 node.js feature that performed a function and then called a callback on success, a separate callback on failure and had timeout functionality as well. A kind reader pointed out this independent implementation.

I am reasonably sure that I can get the code working by dropping that Gist in place. But, since copying and pasting code that I do not understand can only lead to very bad things, I would like to see if I can get it working without promises. When they were removed, it was suggested that they could, for the most part, be replaced with something like:
  method(arg0, arg1, arg2, function (error, result0, result1) { 
puts('complete');
});
Right now, the allDbs() calls look like:
alldbs(couchdbUrl.port, couchdbUrl.hostname, pathname).addCallback(function (dbs) { // do something with dbs })
If my understanding is correct, I should be able to replace that with something like:
alldbs(couchdbUrl.port, couchdbUrl.hostname, pathname, function (dbs) { // do something with dbs})
By pushing the callback function into the argument list, the alldbs() will need to handle the callback directly, without the abstraction of the promises. So let's do it...

I change the first alldbs() call thusly:
  // Deprecated promise-based call:
// alldbs(couchdbUrl.port, couchdbUrl.hostname, pathname).addCallback(attachAllDbs)
alldbs(couchdbUrl.port, couchdbUrl.hostname, pathname, attachAllDbs)
With that, I update the actual function:
var alldbs = function (port, hostname, pathname, callback) {
//var p = new events.Promise();
var client = http.createClient(port, hostname);
var request = client.request('GET', pathname + '_all_dbs');
request.addListener('response', function(response) {
var buffer = '';
response.addListener("data", function(data){buffer += data;});
response.addListener("end", function(){
dbs = JSON.parse(buffer);
//p.emitSuccess(dbs);
callback(dbs);
});
});
request.close();

//return p;
};
Easy-peasy. But does it work?
cstrom@whitefall:~/repos/node.couch.js/changes$ ~/local/bin/node lib/service.js http://127.0.0.1:5984
Error: Promise has been removed. See http://groups.google.com/group/nodejs/msg/0c483b891c56fea2 for more information.
at new <anonymous> (node.js:11:11)
at /home/cstrom/repos/node.couch.js/changes/lib/service.js:115:11
at /home/cstrom/repos/node.couch.js/changes/lib/service.js:158:48
at Array.forEach (native)
at /home/cstrom/repos/node.couch.js/changes/lib/service.js:157:9
at IncomingMessage. (/home/cstrom/repos/node.couch.js/changes/lib/service.js:38:7)
at Client.<anonymous> (http:393:14)
at node.js:810:9
w00t!

Normally a backtrace is not a cause for w00ting, but in this case it is. I have successfully made it past the alldbs invocation and have reached the part of the code that is scanning design documents for change attributes. Not only that, but the backtrace is something that I know how to solve: I need to replace another promise.

I continue working my way through the code, replacing promises with direct callbacks and updating addListener calls to use the new event names. Eventually, I reach this point:
Error: Promise has been removed. See http://groups.google.com/group/nodejs/msg/0c483b891c56fea2 for more information.
at new <anonymous> (node.js:11:11)
at /home/cstrom/repos/node.couch.js/changes/lib/listener.js:65:15
at new <anonymous> (/home/cstrom/repos/node.couch.js/changes/lib/listener.js:77:5)
at [object Object].designDocChange (/home/cstrom/repos/node.couch.js/changes/lib/service.js:74:28)
at /home/cstrom/repos/node.couch.js/changes/lib/service.js:167:52
at Array.forEach (native)
at /home/cstrom/repos/node.couch.js/changes/lib/service.js:167:18
at IncomingMessage.<anonymous> (/home/cstrom/repos/node.couch.js/changes/lib/service.js:131:7)
at Client.<anonymous> (http:393:14)
at node.js:810:9
Ah, I look to have reached the end of the service library. Now it is listener.js that needs updating to a post-promise world. Hopefully I can finish off the changes by tomorrow and will be ready to watch CouchDB changes with node.js.

Day #62

No comments:

Post a Comment