TL DR
DNode
- Provides RMI
- remote functions can take callbacks as arguments;
- which is good because it is completely asynchronous;
- works autonomously or through an existing http-server;
- may have a browser and Node clients;
- supports middleware like
connect ; - has been longer than NowJS.
Nowjs
- goes beyond just RMI and implements a shared API. I like Dropbox , only with variables and functions instead of files;
- remote functions also receive callbacks ( thanks to Shridatta and Eric from NowJS for clarification );
- Depends on the operation of the HTTP listening server;
- only browser clients can have;
- became public just recently;
- now incorrect.
Conclusion
NowJS is more like a toy right now - but keep the watch when it matures. For serious stuff, maybe with DNode. A more detailed overview of these libraries, read together.
DNode
DNode provides a remote method call structure. Both the client and server can expose functions to each other.
// On the server var server = DNode(function () { this.echo = function (message) { console.log(message) } }).listen(9999) // On the client dnode.connect(9999, function (server) { server.echo('Hello, world!') })
The function that is passed to DNode() is a handler that is not like the one passed to http.createServer . It has two parameters: client can be used to access functions exported by the client, and connection can be used to handle connection-related events:
// On the server var server = DNode(function (client, connection) { this.echo = function (message) { console.log(message) connection.on('end', function () { console.log('The connection %s ended.', conn.id) }) } }).listen(9999)
Exported methods can be passed as you like, including functions. They are properly wrapped as a DNode proxy and can be called back to another endpoint. This is basic: DNode is completely asynchronous; it does not block while waiting for the remote method:
// A contrived example, of course. // On the server var server = DNode(function (client) { this.echo = function (message) { console.log(message) return 'Hello you too.' } }).listen(9999) // On the client dnode.connect(9999, function (server) { var ret = server.echo('Hello, world!') console.log(ret) // This won't work })
Callbacks must be passed to receive responses from another endpoint. Complex conversations can become unreadable quite quickly. This question discusses possible solutions to this problem.
// On the server var server = DNode(function (client, callback) { this.echo = function (message, callback) { console.log(message) callback('Hello you too.') } this.hello = function (callback) { callback('Hello, world!') } }).listen(9999) // On the client dnode.connect(9999, function (server) { server.echo("I can't have enough nesting with DNode!", function (response) { console.log(response) server.hello(function (greeting) { console.log(greeting) }) }) })
The DNode client can be scripted inside an instance of Node, or it can be embedded in a web page. In this case, it will only connect to the server that served on the web page. Connect has a lot of help in this case. This script has been tested with all modern browsers and with Internet Explorer 5.5 and 7.
DNode was launched less than a year ago, in June 2010. It has matured as a Node library can be. In my tests, I did not find obvious problems.
Nowjs
NowJS provides a kind of magical API that borders on sympathy. The server has everyone.now scope. Everything that is placed inside everyone.now becomes visible to every client through the now area.
This code on the server will share the echo function with each client that writes the message to the server console:
When the "general" function is executed on the server side, this will have the now attribute, which is typical for the client who made this call.
Functions in NowJS can have return values. To get them, the callback must have passed:
// On the client now.twice(10, function (r) { console.log(r) } // On the server everyone.now.twice = function(n) { return 2 * n }
It matters if you want to pass the callback as an honest argument (not to collect the return value) - you must always pass the return value collector or Now JJ may get confused. According to the developers, this way of getting the return value with an implicit callback is likely to change in the future:
And this is for the NowJS API. Well, actually there are three more functions that can be used to detect client connectivity and disconnect. I do not know why, however, they did not display these functions using an EventEmitter .
Unlike DNode, NowJS requires the client to have a script running inside a web browser. The page containing the script must be served by the same Node that the server is running.
On the server side, NowJS also needs to listen on the HTTP server. It must be accepted when initializing NowJS:
var server = http.createServer(function (req, response) { fs.readFile(__dirname + '/now-client.html', function (err, data) { response.writeHead(200, {'Content-Type':'text/html'}) response.write(data) response.end() }) }) server.listen(8080) var everyone = now.initialize(server)
The first fix for NowJS is a couple of weeks ago (March 2011). So be a buggy. I myself found questions when writing this answer. We also expect the API to change a lot.
On the plus side, developers are very accessible - Eric even led me to create callbacks. The source code is not documented, but, fortunately, is simple and short, and the user manual and examples are enough to get started.