Saturday, July 12, 2014

Node Console Module

console

console

The console module is straightforward. As with anything, there’s bound to be something of interest if we look closely.

stdout

console.log([data], […])
console.info([data], […])

Print to stdout. You can use printf formatting.

console.dir(obj)

Logs result of util.inspect.

Time

console.time(label)
console.timeEnd(label)

These are cool methods for timing how long something takes.

console.time('foo');

setTimeout(function () {
  console.timeEnd('foo');
}, 300);

// prints "foo: 303ms"

stderr

console.error([data], […])
console.warn([data], […])

Print messages, like log and info, but to stderr.

console.trace(label)

Prints a stack trace.

var f1 = function (fn) {
  // step 4
  // step 6
  fn();
};

var f2 = function iHaveAName () {
  // step 3
  f1(function soDoI () {
    // step 5
    f1(function () {
      // step 7
      console.trace('a label');
    });
  });
};

var f3 = function () {
  // step 2
  f2();
};

var f4 = function () {
  // step 1
  f3();
};

f4();

console output

Trace: a label
    at /home/grizzle/code/node-study/modules/console.js:15:15
    at f1 (/home/grizzle/code/node-study/modules/console.js:6:3)
    at soDoI (/home/grizzle/code/node-study/modules/console.js:13:5)
    at f1 (/home/grizzle/code/node-study/modules/console.js:6:3)
    at iHaveAName (/home/grizzle/code/node-study/modules/console.js:11:3)
    at f3 (/home/grizzle/code/node-study/modules/console.js:22:3)
    at f4 (/home/grizzle/code/node-study/modules/console.js:27:3)
    at Object.<anonymous> (/home/grizzle/code/node-study/modules/console.js:30:1)
    at Module._compile (module.js:449:26)
    at Object.Module._extensions..js (module.js:467:10)

Notice that it’s pretty good at figuring out which method the stack is in, but if it’s an anonymous function, there’s not name to print.

console.assert(expression, [message])

Throws an error if expression is falsy.

Summary

That’s it. There’s not much to it, so get on to the next module. If you’re interested, here’s the source.

Friday, July 11, 2014

Node: events module

Notes on the events Module

Anything in node that emits events is an instanceof events.EventEmitter.

Emitting Events

It’s easy to make an EventEmitter emit an event.

var events = require('events');
var emitter = new events.EventEmitter();

emitter.emit('foo');

You can include arguments after the event name, if you need to. emit returns true if anyone was listening for the event.

var isThereAnybodyInThere = emitter.emit('foo', 1, false, 'boo');
console.log(isThereAnybodyInThere); // false

That’s all there is to events, but it doesn’t do much without listeners.

Adding Listeners

Listeners are functions attached to an EventEmitter that are executed when the EventEmitter emits an event. Inside an event listener, this is the EventEmitter.

Use these methods to add listeners to EventEmitters.

emitter.addListener(event, listener)
emitter.on(event, listener)
emitter.once(event, listener)

addListener and on are the same thing. Listeners added with once are removed the first time they are executed. All three methods are chainable.

var events = require('events');
var emitter = new events.EventEmitter();

var fooHappened = function () {
    console.log('foo happened');
};

var barHappened = function () {
    console.log('bar happened');
};

var bazHappened = function () {
    console.log('baz happened');
};

emitter
    .addListener('foo', fooHappened)
    .on('bar', barHappened)
    .once('baz', bazHappened);

emitter.emit('foo');
emitter.emit('foo');
emitter.emit('bar');
emitter.emit('bar');
emitter.emit('baz');
emitter.emit('baz');

console output

foo happened
foo happened
bar happened
bar happened
baz happened

Each time a listener is added, newListener is emitted by the EventEmitter.

Who is Listening?

You can find out what listeners are attached with listeners().

var events = require('events');
var emitter = new events.EventEmitter();
var listener = function iAmACoolListener () {};
var listener2 = function iAmALameListener () {};

emitter.on('foo', listener);
emitter.on('foo', listener2);
emitter.on('bar', listener2);

console.log(emitter.listeners('foo'));
console.log(emitter.listeners('bar'));
console.log(emitter.listeners('baz'));

console output

[ [Function: iAmACoolListener], [Function: iAmALameListener] ]
[ [Function: iAmALameListener] ]
[]

Maybe you don’t want that much detail. If you only want to know how many listeners are registered for an event on an EventEmitter, use the class method listenerCount().

var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
var listener = function iAmACoolListener () {};
var listener2 = function iAmALameListener () {};

emitter.on('foo', listener);
emitter.on('foo', listener2);
emitter.on('bar', listener2);

console.log(EventEmitter.listenerCount(emitter, 'foo'));
console.log(EventEmitter.listenerCount(emitter, 'baz'));

console output

2
0

Too Many Listeners?

You can set a max number of listeners for an EventEmitter with setMaxListeners(). If you go over, you get a nice warning message. By default, this value is set to 10.

var events = require('events');
var emitter = new events.EventEmitter();
var i = 10;
var listener = function () {};

emitter.setMaxListeners(i - 1);

while (i) {
    i--;
    emitter.on('foo', listener);
}

console output

(node) warning: possible EventEmitter memory leak detected. 10 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at EventEmitter.addListener (events.js:160:15)
    at Object.<anonymous> (C:\Users\jgreer.IPSWITCH_M\code\node-study\modules\events.js:14:13)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
    at node.js:906:3

Removing Listeners

You can remove a listener with removeListener(). Note that it is chainable, which is cool, but it doesn’t tell you if the removal was successful. When an event is successfully removed, the EventEmitter emits the removeEvent event.

var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
var listener = function iAmACoolListener () {};
var listener2 = function iAmALameListener () {};

// add some listeners
emitter
    .on('foo', listener)
    .on('foo', listener2)

    // Don't declare listeners like this because it's hard
    // to remove them.
    .on('foo', function () {})

    // log when listeners are removed
    .on('removeListener', function (event, listener) {
        console.log('removed', event, listener);
    });

// How many foo listeners are there?
console.log(EventEmitter.listenerCount(emitter, 'foo'));

// Remove some listeners.
emitter
    .removeListener('foo', listener)
    .removeListener('foo', listener2)
    .removeListener('foo', function () {});

// Hmm... We can't remove the last one because we declared the
// listener inline.
console.log(EventEmitter.listenerCount(emitter, 'foo'));

// We can get a reference to it, but it's ugly.
var listeners = emitter.listeners('foo');
emitter.removeListener('foo', listeners[0]);

// Now it's gone.
console.log(EventEmitter.listenerCount(emitter, 'foo'));

console output

3
removed foo function iAmACoolListener() {}
removed foo function iAmALameListener() {}
1
removed foo function () {}
0

You can remove all listeners for an event with removeAllListeners(event), but that’s a little heavy-handed, especially if you didn’t create the EventEmitter.

That’s It

Now you’re an expert on Node’s events module.

Thursday, July 10, 2014

Node Buffers

buffer

This post contains all you need to know about Node.js’s buffer module. It’s easier than you think.

What’s a Buffer?

Buffers are used for handling octet streams (sequential chunks of data) because, surprise, not all files are text files. A buffer is like an array of octets (bytes).

The buffer module is at the core of Node, so it’s global. There’s no need to require it before using the Buffer class.

How to Create a Buffer

There are three ways to create a Buffer.

  1. new Buffer(size)

    Pass the length of the new Buffer to the constructor, and you’ll get a Buffer with size octets.

  2. new Buffer(array)

    Got an array of octets but wish you could use cool Buffer methods? Pass the array into the constructor and wish no longer.

  3. new Buffer(str, [encoding])

    Pass a string into the constructor and it will be encoded into octets. By default, the encoding is ‘utf8’.

How to Use a Buffer

Basic Stuff

Access a specific octet with the [] operator, just like an Array.

> var b = new Buffer([1, 2, 3]);
undefined
> b[2]
3
> b[2] = 9;
9
> b[2]
9

The length of the Buffer is available as length, surprise! This is the size of the memory set aside for the Buffer, not the length of the set octects. Technically, you can change the length, but it may break your Buffer. Only get it, don’t set it.

> var b = new Buffer(10);
undefined
> b.length
10
> b.length = 11;
11
> b
RangeError: out of range index

Methods

There are a lot of buffer methods, but if you categorize them like this, it’s less intimidating.

Standard

  • copy
  • fill
  • slice
  • toJSON
  • toString

Static Methods

  • byteLength
  • concat
  • isBuffer
  • isEncoding

Read/Write Methods

This makes up the majority, but they follow a pattern.

Methods Explained

copy

buf.copy(targetBuffer, [targetStart], [sourceStart], [sourceEnd])

Copy a section of one buffer into another.

fill

buf.fill(value, [offset], [end])

Fill a buffer with a value. This is a good idea since a newly created buffer may have “dirty” memory in it. See?

> var b = new Buffer(100)
undefined
> b.toString()
'\u0000\u0000��6=�\u0000\u0000�9^\u0001\u0000\u0000\u0000\u0000�9^\u0001\u0000\u0000\u0000\u0000\n\u0000\u0000\u0000\u0000\u0000\u0000\u0000h:^\u0001\u0000\u0000\u0000\u0000\u0005\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000�����\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0000\u0000\u0000\u0002\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000'

slice

buf.slice([start], [end])

Crop a section of the buffer into a new buffer. The returned buffer references the same memory, so changing one will change both.

toJSON

buf.toJSON()

Returns POJO with buffer info.

toString

buf.toString([encoding], [start], [end])

Converts octets to string. The default encoding is ‘utf8’.

byteLength

Buffer.byteLength(string, [encoding])

See how many bytes it takes to encode a string. For complex characters, this may be longer than the string’s length.

concat

Buffer.concat(list, [totalLength])

Returns an array of buffers (list) combined into one new buffer.

isBuffer

Buffer.isBuffer(obj)

Check if obj is a buffer. If you think there’s a reason to use this, you’re wrong.

var b = new Buffer(10);
undefined
> var jsonB = b.toJSON();
undefined
> jsonB
{ type: 'Buffer', data: [ 0, 0, 0, 0, 40, 30, 94, 1, 0, 0 ] }
> Buffer.isBuffer(jsonB)
false

This is stupid, as it’s just an instanceof check. I suppose it’s OK to use in case one day it does something more. For now, this is it.

> Buffer.isBuffer.toString()
'function isBuffer(b) {\n  return util.isBuffer(b);\n}'
> util.isBuffer.toString()
'function isBuffer(arg) {\n  return arg instanceof Buffer;\n}'

isEncoding

Buffer.isEncoding(encoding)

Test to see if an encoding is something buffers know how to work with.

Read/Write Methods

I’m not going to bother explaining each of these, but I’ll give you a few hints.

Int16: 16 bit integer
UInt16: unsigned 16 bit integer
LE: Little Endian
BE: Big Endian
noAssert: Don’t verify this is a valid range within the buffer.

buf.readDoubleBE(offset, [noAssert])
buf.readDoubleLE(offset, [noAssert])
buf.readFloatBE(offset, [noAssert])
buf.readFloatLE(offset, [noAssert])
buf.readInt16BE(offset, [noAssert])
buf.readInt16LE(offset, [noAssert])
buf.readInt32BE(offset, [noAssert])
buf.readInt32LE(offset, [noAssert])
buf.readInt8(offset, [noAssert])
buf.readUInt16BE(offset, [noAssert])
buf.readUInt16LE(offset, [noAssert])
buf.readUInt32BE(offset, [noAssert])
buf.readUInt32LE(offset, [noAssert])
buf.readUInt8(offset, [noAssert])

buf.write(string, [offset], [length], [encoding])

buf.writeDoubleBE(value, offset, [noAssert])
buf.writeDoubleLE(value, offset, [noAssert])
buf.writeFloatBE(value, offset, [noAssert])
buf.writeFloatLE(value, offset, [noAssert])
buf.writeInt16BE(value, offset, [noAssert])
buf.writeInt16LE(value, offset, [noAssert])
buf.writeInt32BE(value, offset, [noAssert])
buf.writeInt32LE(value, offset, [noAssert])
buf.writeInt8(value, offset, [noAssert])
buf.writeUInt16BE(value, offset, [noAssert])
buf.writeUInt16LE(value, offset, [noAssert])
buf.writeUInt32BE(value, offset, [noAssert])
buf.writeUInt32LE(value, offset, [noAssert])
buf.writeUInt8(value, offset, [noAssert])

Unmentionables

Technically, these are in the buffer module as well and, since I promised this is all you need to know, I will mention them. Don’t even bother to read this, though.

buffer.INSPECT_MAX_BYTES

This determines how many bytes are returned when inspecting the buffer. Of course, this only applies to modules loaded with require, and there’s no reason to require the buffer module since it’s already there.

Class: SlowBuffer

This is an internal class used to speed up how memory is grabbed. The docs explicitly say not to use this.