LineDelimited JSON (LDJ) protocol
LineDelimited JSON (LDJ) protocol

The protocol that use newlines to separate messages, we’ll call this protocol Line Delimited JSON (LDJ). There are no line breaks in JSON messages. Although JSON is whitespace agnostic it ignores whitespace outside of string value.

Serializing Messages with JSON

Let’s develop the message-passing protocol that uses JSON to serialize messages. Each message is a JSON-serialized object, which is a hash of key-value pairs. Here’s an example JSON object with two key-value pairs:

{"key":"value","anotherKey":"anotherValue"}

The net-watcher service we’ve been developing in this chapter sends two kinds of messages that we need to convert to JSON:
When the connection is first established, the client receives the string
Now watching target.txt for changes…
Whenever the target file changes, the client receives a string like this: File “target.txt” changed: Sat Jan 12, 2013, 12:35:52 GMT-0500 (EST)
We’ll encode the first kind of message this way:

{"type":"watching","file":"target.txt"}

The type field indicates that this is a watching message the specified file is now being watched.
The second type of message is encoded this way:

{"type":"changed","file":"target.txt","timestamp":1358175733785}

Here the type field announces that the target file has changed. The timestamp field contains an integer value representing the number of milliseconds since midnight, January 1, 1970. This happens to be an easy time format to work within JavaScript. For example, you can get the current time in this format with Date.now().

To relieve the client program from the danger of split JSON messages, we’ll implement Line Delimited JSON (LDJ) buffering client module. Then we’ll incorporate it into the network-watcher client.

First, let’s have a look at how the Node does inheritance. The following code sets up LDJClientto inherit from EventEmitter.

const
    events=require('events'),
    util=require('util'),
    //clientconstructor
    LDJClient=function(stream){
        events.EventEmitter.call(this);
    };
util.inherits(LDJClient,events.EventEmitter);

LDJClient is a constructor function, which means other code should call new LDJClient(stream) to get an instance. The stream parameter is an object that emits data events, such as a Socket connection. Inside the constructor function, we call the EventEmitter constructor on this. That line of code is roughly equivalent to calling super() in languages with classical inheritance.

Finally, we call util.inherits() to make LDJClient’s prototypal parent object the EventEmitterprototype. If this sounds cryptic to you, don’t worry. It’s like saying classLDJClientinherits from EventEmitter in languages with a classical inheritance model. It means that if you look for a property on an LDJClientand it’s not there, the EventEmitteris the next place to look

Exporting Functionality in a Module
Let’s pull together the previous code samples and expose LDJClientas a module. Open a text editor and insert the following: /ldj.js

"usestrict";
const
    events=require('events'),
    util=require('util'),
//clientconstructor
    LDJClient=function(stream){
        events.EventEmitter.call(this);
        let
            self=this,
            buffer='';
        stream.on('data',function(data){
            buffer+=data;
            letboundary=buffer.indexOf('\n');
            while(boundary!==-1){
                letinput=buffer.substr(0,boundary);
                buffer=buffer.substr(boundary+1);
                self.emit('message',JSON.parse(input));
                boundary=buffer.indexOf('\n');
            }
        });
    };
report erratum •discuss
Extending Core Classes in Custom Modules • 37
www.it-ebooks.info
util.inherits(LDJClient,events.EventEmitter);
//exposemodulemethods
exports.LDJClient=LDJClient;
exports.connect=function(stream){
    returnnewLDJClient(stream);
};

To create an LDJClientinstance.
Code to use the LDJ module will look something like this:

const
    ldj=require('./ldj.js'),
    client=ldj.connect(networkStream);
client.on('message',function(message){
    //takeactionforthismessage
});

LEAVE A REPLY

Please enter your comment!
Please enter your name here