Wednesday, October 1, 2014

MongoDB Aggregation

Aggregation

Basic read operations are fine, but what about looking at the documents and computing results? To do that, we'll need to use aggregations.

First off, let's seed our database with some data we can aggregate.

var i = 40;
var names = 'George|Samuel|Thomas|Benjamin|John'.split('|');
var colors = 'Red|Orange|Yellow|Blue|Green|Indigo|Violet'.split('|');

while (i--) {
    db.people.insert({
        name: names[i % names.length],
        number: i,
        color: colors[i % colors.length],
        rand: Math.random()
    });
}

Whet Your Whistle

The aggregation docs are pretty deep, especially when you're just looking for a simple answer. So, to keep up the motivation, here's a quick taste of grouping.

db.people.aggregate([
    {
        $group: {
            _id: '$color',
            count: {
                $sum: 1
            }
        }     
    }
]);
{
    "result" : [
        {
            "_id" : "Red",
            "count" : 6
        },
        {
            "_id" : "Indigo",
            "count" : 5
        },
        {
            "_id" : "Violet",
            "count" : 5
        },
        {
            "_id" : "Orange",
            "count" : 6
        },
        {
            "_id" : "Yellow",
            "count" : 6
        },
        {
            "_id" : "Blue",
            "count" : 6
        },
        {
            "_id" : "Green",
            "count" : 6
        }
    ],
    "ok" : 1
}

Whoa, Nellie!

Aggregation can be confusing when you first run into it, which usually happens when trying to figure out how to do grouping. That's why I've shown $group above, but it's is actually one of the trickier aggregation stages.

I suggest slowing down and learning how aggregation works at a high level to allow the concepts to sink in. Once you get that, the specifics are easily demystified by referring to the docs.

How Does Aggregation Work?

Simply put, aggregation takes a collection of documents and turns them into a new collection of documents. Each of these transformations is referred to as an aggregation stage. How each aggregation stage works varies, but you can figure them out easily once you understand what you're looking at.

Aggregation works by passing a collection through a series of stages, each changing the collection and passing it off to the next stage. This is the aggregation pipeline.

An Example

db.people.aggregate([
    // Change the documents in people by sorting.
    { $sort: { name: -1 } },

    // Change the sorted documents from the previous stage
    // by limiting them to the first 3.
    { $limit: 3 },

    // Change which fields are present in the
    // 3 sorted documents.
    { $project: { _id: 0, name: 1, color: 1 } }
]);

{
    "result" : [
        {
            "name" : "Thomas",
            "color" : "Violet"
        },
        {
            "name" : "Thomas",
            "color" : "Green"
        },
        {
            "name" : "Thomas",
            "color" : "Yellow"
        }
    ],
    "ok" : 1
}

What is the Result?

This makes sense, but what is this new object structure? It's not a collection like we saw in the CRUD post. According to TFM, it is a cursor.

Remember, in mongo, the shell interface, cursors are printed out automatically when you don't assign the operation to a variable.

So, it says it's a cursor, and it has the documents in result, but there's definitely something different. Let's compare the keys in the two different cursor types.

var findCursor = db.people.find();
var aggregateCursor = db.people.aggregate([{ $limit: 10 }]);

Object.keys(findCursor).sort();

[
    "_batchSize",
    "_collection",
    "_cursor",
    "_db",
    "_fields",
    "_limit",
    "_mongo",
    "_ns",
    "_numReturned",
    "_options",
    "_query",
    "_skip",
    "_special"
]

Object.keys(aggregateCursor).sort();

[ "ok", "result" ]

Now, those don't appear to be the same, but cursors warrant their own post.

Tips for Working Through Aggregation

In my first draft, I got right into explaining each of the rabbit holes in the aggregation stages. That's dumb. Instead, I would like to teach you to fish.

Plan it Out

Figure out what it is you want to do, like this.

db.people.aggregate([
    // group by color

    // sort by count of color

    // pick the top 2

    // remove all the fields except the color
]);

Pick the Stages

There are only 10 aggregation stages. Read the descriptions to see which one(s) you want to you use.

db.people.aggregate([
    // group by color
    { $group: {} },

    // sort by count of color
    { $sort: {} },

    // pick the top 2
    { $limit: {} },

    // remove all the fields except the color
    { $project: {} }
]);

Set the Stages Up

Now that you know what stages you'll use, go through them one-by-one and read the docs. With our cheatsheet, you can keep your eyes on the prize. It's less likely to you'll be overwhelmed or distracted by all the new concepts and terminology that come along with aggregation.

Right at the top of each stage's docs, it shows the structure we need to use. Additionally, they include lots of detail and several examples. Just fight the temptation to get distracted.

If you can, you should end up with something like this.

db.people.aggregate([
    // group by color
    {
        $group: {
            _id: '$color',
            count: {
                $sum: 1
            }
        }
    },

    // sort by count of color
    { $sort: { count: -1 } },

    // pick the top 2
    { $limit: 2 },

    // remove all the fields except the color
    {
        $project: {
            _id: 0,
            color: '$_id'
        }
    }
]);

{
    "result" : [
        {
            "color" : "Orange"
        },
        {
            "color" : "Red"
        }
    ],
    "ok" : 1
}

References

Friday, September 26, 2014

MongoDB CRUD: Part II

Welcome to part two of our excellent adventure. Before we resume, let's seed our database with some more documents to play with.

var max = 33;
while (max--) {
    db.stomach.insert({
        name: 'Oreo',
        part: max % 3 === 0 ? 'white' : 'black'
    });
}

Update

Now that we've got a bunch of Oreos in our stomach collection, I don't think the Sweetwater we added in Part I was such a good idea. Let's change it.

  1. Find the documents we want to update. We'll do that with another query.
  2. Specify the new values. That's done with the update parameter.
db.stomach.update(
    // query
    { beer: 'Sweetwater' },

    // update parameter
    {
        $set: {
            beer: 'root'
        }
    }
);

We changed the document's beer value from 'Sweetwater' to 'root'. This did not affect the other fields in the document, as you can see.

db.stomach.find({
    beer: {
        $exists: true
    }
}).pretty();

{
    "_id" : ObjectId("5424a5ba28f262081e997a7f"),
    "beer" : "root",
    "count" : 2
}

What if we want to completely replace the fields in the document, though? Who wants rootbeer with cookies? Let's make it more complimentary to the other documents in the collection.

db.stomach.update(
    // query
    {
        beer: {
            $exists: true
        }
    },

    // update parameter
    {
        drink: 'milk',
        type: 'skim',
        ounces: 8
    }
);

By specifying a plain object as the update parameter instead of update operators, we've completely changed the document.

> db.stomach.find({ drink: 'milk' }).pretty();
{
    "_id" : ObjectId("5424a5ba28f262081e997a7f"),
    "drink" : "milk",
    "type" : "skim",
    "ounces" : 8
}

Note that the _id does not change when using update, even when replacing the document.

Now, let's change all those old-fashioned Oreos to one of the new flavors.

db.stomach.update(
    // query
    {
        name: 'Oreo',
        part: 'white'
    },

    // update parameter
    {
        $set: {
            part: 'berry'
        }
    }
);

Let's see the results.

> db.stomach.find({ name: 'Oreo', part: 'berry' }).pretty();
{
    "_id" : ObjectId("542603ba21330a1f47f4bd68"),
    "name" : "Oreo",
    "part" : "berry"
}

Only one of the documents was updated. This brings us to the 3rd parameter of update, the options. The options are described in the documentation, one of which is multi.

db.stomach.update(
    // query
    {
        name: 'Oreo',
        part: 'white'
    },

    // update parameter
    {
        $set: {
            part: 'berry'
        }
    },

    // options
    {
        multi: true
    }
);
> db.stomach.find({ name: 'Oreo', part: 'berry' }).count();
11

By default, update only modifies a single document. With multi, we can make it update all the documents matched by our query.

Delete

Now we've got a stomach collection full of berry cookies and milk, the anchovy pizza isn't really sitting well. Let's barf it up.

db.stomach.remove({
    anchovies: {
        $exists: true
    } 
});

That should seem pretty intuitive by now.

References


Check out the accompanying Github repo to these posts about MongoDB/Mongoose.

Thursday, September 25, 2014

MongoDB CRUD: Part I

In a previous post, I wrote the "M" in MEAN really stands for Mongoose as it is the de facto way to work with MongoDB. However, it's interesting to peek beneath the surface. You don't have to be able to rebuild a manifold in order to drive, but you should probably know how to check the oil.

So, now that we know how to connect, let's figure out how to CRUD documents.

Create

Databases contain collections. Collections contain documents. To insert a new document into a collection, we use the insert method.

db.stomach.insert({
    crust: 'thin',
    pepperoni: true,
    olives: true,
    anchovies: 6
});

Easy, right? That inserted a pizza-like document into the stomach collection. Let's try it again.

db.stomach.insert({
    beer: 'Sweetwater',
    count: 2
});

Pretty straightforward. Also, this demonstrates why NoSQL databases are so cool; documents within a collection don't have to have to the same fields. Collections are like tables, but friendlier. Do you remember going into admin mode and creating the stomach table before we ran these queries?

Exactly.

Read

Now that's we've got a collection and a couple documents, let's see about reading them. What was our collection's name again?

> show collections
stomach
system.indexes

Oh, yeah, stomach. Let's see what's in there.

> db.stomach.find().pretty();
{
    "_id" : ObjectId("5424a39628f262081e997a7e"),
    "crust" : "thin",
    "pepperoni" : true,
    "olives" : true,
    "anchovies" : 6
}
{
    "_id" : ObjectId("5424a5ba28f262081e997a7f"),
    "beer" : "Sweetwater",
    "count" : 2
}

As you can see, MongoDB inserted a unique _id for us because we didn't include one.

find can take a couple arguments to make it more useful.

  • an object of query operators - This specifies what documents you're looking for.
  • an object of projection operators - This specifies what fields you want returned in the results.
db.stomach.find(
    {
        anchovies: {
            $exists: true
        }
    },

    {
        crust: 1,
        pepperoni: 1,
        donkey: 1
    }
);

I'm not going to go over all the options as the documentation is very good, but you get the idea. A couple notes, though.

  • It's worth noting that find returns a cursor that you can iterate through to see the returned documents. Because we didn't assign the expression to a variable, mongo printed out the first 20 results automatically.
  • _id is returned unless you explicitly exclude it in the projection. You can't mix includes and excludes in your projection with the exception of the _id field.
  • We included donkey in the projection, but it doesn't exist. Therefore, it was not in the result.

Summary

My wife just turned on Bill a Ted and it's surprisingly distracting. That means, Update and Delete will come in part II of this post. Party on, dudes!

References


Check out the accompanying Github repo to these posts about MongoDB/Mongoose.

Wednesday, September 24, 2014

Connecting to MongoDB

Connecting to MongoDB with Mongoose is really easy.

mongoose.connect('mongodb://localhost/my-cool-database');

Suppose you want to poke around your database outside of Mongoose, though. How do you connect? Use mongo, the shell interface.

Basic Connection

This connects to the "test" database on "localhost".

mongo

Another Machine/Database

You can specify a different machine and/or database by specifying the "database address."

# connect to another database (on localhost)
mongo some-other-db

# connect to another machine/database
mongo whatever.com/some-db

Warning

You can connect to a machine without specifying a database, but this is NOT how to do it.

mongo localhost

This will connect you to "localhost" using the database "localhost." If you want to connect without automatically selecting a database, use the --nodb option.

mongo localhost --nodb

From there, you can connect to a database manually.

Change Port

By default, MongoDB runs on port 10027. If you're running on a different port, just include that in the "database address."

mongo whatever.com:12345/some-db

Close Connection

Now you can connect to your MongoDB in a few different ways. Since we haven't covered anything else yet, the final thing you need to learn is how to disconnect. Baby steps, right?

You can close the connection with exit or ctrl + c.


Check out the accompanying Github repo to these posts about MongoDB/Mongoose.

Monday, September 22, 2014

IIFE Mania

At work today, I noticed someone using an IIFE that was completely pointless. The only possible rationalization was, "I saw it on SO and don't really understand JavaScript." So, allow me to elucidate.

An IIFE creates a tidy new scope for you to do your magic in. This is especially good if you're creating modules.

Protecting Global Namespace

The scope created can act like a safety net to keep you from accidentally declaring global variables. Implied globals, however, slip right through. That's cool, but your linter should catch these mistakes.

non-IIFE

// blatant new global variable
var foo = 1;

// an implied global
bar = 1;

IIFE

(function () {
    // foo stays out of the global namespace
    var foo = 1;

    // implied globals are still global
    bar = 1;
}());

console.log(bar);

Passing Arguments

Perhaps my colleague thought passing arguments into his function provided some benefit. Though, the arguments passed in were globals we provide. It's not a $ conflict situation.

This is the aspect that really made me scratch my head.

Does passing arguments somehow protect them? No, because they're the same reference.

var foo = { original: true };

(function (localFoo) {
    console.log(localFoo === foo);  // true
    console.log(localFoo.original); // true
}(foo));


// evil code messing up our precious global
foo.original = false;

As long as your function executes before that other evil code messes with the global, you're good. But wait...

var foo = { original: true };

console.log(foo.original); // true

// evil code messing up our precious global
foo.original = false;

That gets you the same result since your code executed before the evil code.

What if you're trying to insulate the outside world from your changes to the globals?

var foo = { original: true };

(function (foo) {
    foo.original = false;
}(foo));

console.log(foo.original); // false

Oh, yeah. They're the same reference. There's no benefit to passing these in.

Why Ever Pass Arguments?

There are a few situations where it's a good idea to pass arguments into an IIFE.

Aliasing

If you want to use a different name for the global, that's cool. This is how jQuery gets around other libraries that use $. It's a nice way for you to pick what you want to call the global.

This example attempts a lame joke by reference.

var foo = { original: true };

(function (al) {
    console.log(al.original);
}(foo));

Super Fast Code

Another good time to pass arguments into your IIFE is when you've optimized every other frigging thing in your code and you just have to speed it up some more. Technically, providing the parameter creates a reference to the global variable inside the function's scope. That means, wherever your code references the global, it won't have to look up the scope chain until it finds it in the stratosphere.

That's kind of a stretch, though.

Conclusion

IIFEs have a proper place, including those with arguments. Primarily, it's to carve out a nice private chunk of scope for you to work in. If you're not declaring any variables or functions, you don't need this.

Passing arguments into an IIFE looks really cool like all the stuff you've seen online, but there aren't many reasons to do it. If you do it when it's pointless, it just makes you look like a jackass.

Friday, September 19, 2014

The Lazy Way to Write a Blog

start 8:42 pm

I rarely find time to sit down and write a blog. When I do, it's annoying how much time is wasting using this clunky WYSIWYG. It's not perfect, but here's what I've come up with to stream line the process.

Use Sublime

Screw writing in the browser. I live in ST3, so why not stay there?

Use Markdown

Writing HTML is for chumps; use Markdown.

Use Markdown Preview

Install the Makdown Preview package. When you're done previewing and want post your blog, use ctrl + shift + p, "Markdown Preview: Copy to Clipboard". Select the github option.

Create a new file, paste the contents, and delete everything except the body content. It will be a little unreadable, with lots of styles, but it's not hard to search for the body tag. You're in Sublime, right?

<!DOCTYPE html><html><head><meta charset="utf-8"><style></style> <title>blah</title></head><body><article class="markdown-body"><p>blah blah blah</p></article></body></html>

Take the remaining content and paste it into your blog.

Add the CSS

In Blogger, and probly other blogs, you can add global CSS for your pages. Use this CSS, which is the same stuff you just clipped out of your preview in the step before.

Summary

Now, you can crank out blogs that look reasonably well. The important thing for me is how code snippets look.

(function () {
    'use strict';

    var formatted = true;

    console.log('They look ' + (formatted ? 'good' : 'crappy') + '.');
}());

So, that's it. I haven't quite figured out how to deal with images, but this isn't bad. As you can see, including looking up references, it only took 21 minutes to write this.

end 9:03 pm

Hello, MongoDB

Update: Check out the accompanying Github repo to these posts about MongoDB/Mongoose.


Learning the MEAN stack is fun, especially Node and Angular.  There's a lot to get into just in those two parts, but eventually you're going to want to save some data.  (If not, try out my npm module that fakes persistence.)

So let's learn about the "M."

MEAN is supposed to be MongoDB, Express, AngularJS, and Node, but the "M" really seems to stand for Mongoose, a modeling system.  It's MongoDB underneath, but you don't really have to deal with it directly.


Mongoose Essentials

Define a Schema

The schema describes the object you're going to work with.
var mongoose = require('mongoose');

var dudeSchema = mongoose.Schema({
    name: String,
    age: Number,
    height: Number,
    isMale: Boolean
});

Create a Model

Use your schema to create a model.

var Dude = mongoose.model('Dude', dudeSchema);

Use the Model for CRUDing

var gw = new Dude({
    isMale: true,
    name: 'George Washington'
});

gw.save(function (err, run) {
    if (err) {
        res.status(500).send(err);
    } else {
        res.json(run);
    }
});
This is just the very basics to help you get your bearings.  We'll get more complex later.

references

Thursday, September 18, 2014

$scope or this?

Why is it that the Angular JS docs use $scope in controllers and not this?

It's because they're not the same thing.  The scope that is injected into the controller is prepared before the controller is created.

During the compilation phase, DOM elements, nodes, with directives are found.  Then different types of linking functions are created for each of the nodes based on if the nodes have children or not.

During the linking phase, Angular loops through all of the nodes and links them, pairs them up with a scope.  The `nodeLinkFn` then creates the scope, either brand new or inherited from an outer scope.

childScope = scope.$new();

jqLite attaches this new scope to the node.

jqLite.data(node, '$scope', childScope);

Then, based on the type of linking function that was created, the scope is then tied to the controller.

// locals is a bunch of attributes for the controller, including $scope
controllerInstance = $controller(controller, locals);


$controller is a service that is used to look up the controller we're asking for.  The controller definitions were already created, this just looks up the injected stuff and the constructor function.  Then the injection happens.

instance = $injector.instantiate(expression, locals);

During the instantiation, the constructor function's prototype, the one we wrote, is assigned to the new `Constructor` object's prototype.  Then a new `Constructor` instance is created.  This is all really just standard JS inheritance footwork.  The next part is what we've been waiting for.

`invoke` is called, which actually injects the dependencies into our shiny new object.  This is how the '$scope' dependency we referenced when writing our controller gets set up to be the `$scope` argument within our function.  Finally, our function is called with the new polished `Constructor` instance as its scope.

// fn is the function we injected
// self is the new Constructor object
// args are all the prepared dependencies
return fn.apply(self, args);


So, we're finally inside the controller from our perspective.  Now it should make some sense.

app.controller('FooCtrl', ['$scope', function ($scope) {
    // `this` is the new Constructor object.
    // `$scope` is the scope our controller is tied to the directive with.

    this.message = 'I will not be available to directives.';
    $scope.message = 'I will be.';
}]);

This highlights something, though.  If `$scope` is the context in which the directive is tied to the controller, isn't `this === $scope` within methods of the controller?  Also, `this` is used for inheritance, `$scope` is used for communicating with the directive, what about this gap that local variables live in?

app.controller('FooCtrl', ['$scope', function ($scope) {

    // Local variables can hide out here safely.
    var privateMessage = 'I am available through a closure.';

    // This is pointless.  We're adding `message` to the Constructor object.  Pretty dumb.
    this.message = 'I will not be available to directives.';

    // Being well-behaved, we use $scope like it taught us to in the docs.
    $scope.message = 'I will be available.';

    // Controller methods are called within the context $scope.
    $scope.doClick = function () {
     
        // You could use `this`, but it may lead to confusion.  With all the trickiness,
        // wouldn't it be better to be explicit?
        // $scope === this
        this.message = privateMessage;
    };
}]);

OK, I feel better.  We're going to keep using $scope, but now we'll know why.

Friday, August 8, 2014

Node.js API - How to RTFM

So, you've decided to RTFM? That's great, but there's a reason no one's doing it. Does this sound familiar?

You start reading and you run across a reference you don't get. So, you add a mental sticky note to mark your place and jump off to learn what an EventEmitter is. While your reading, you run across util.inspect. You're not sure what that is, so you add another placeholder and jump over to learn about it. While you're trying to understand the util module, you realize you're not exactly sure how module loading really works. You jump over to the modules section. Eventually, you forget why the hell you wanted to learn Node and start watching Futurama.

That's pretty common in my experience. It's a shame, because the documentation is pretty thorough, there's just not any direction. It's akin to studying English by reading the dictionary. Ignoring the question of if this is a good way to learn Node or not, wouldn't it be cool if it were an option?

Well, there's a pretty straightforward solution.

I went through the entire API and noted the external references mentioned in each section. After this exercise, I understood why I kept getting lost. Here's a diagram of each module and its dependent modules (those that you need to understand first).

I thought this would be a good study guide, but it was intimidating. Since I'm lazy, I took my list of modules and their dependencies and transormed them to json. Then, I wrote a script to embellish the dependencies a bit, by recursively including their dependencies. The results were then de-duplicated and with a little more parsing, I was able to see each module and those that should come before and after.

{
  name: 'process',
  before: ['console', 'events', 'module', 'stream', 'util'],
  after: ['child_process', 'cluster', 'crypto', 'domain', 'fs', 'global', 'http', 'https', 'net', 'readline', 'repl', 'tls_(ssl)', 'tty', 'zlib']
},
{
  name: 'fs',
  before: ['console', 'events', 'module', 'process', 'stream', 'util'],
  after: ['crypto', 'domain', 'https', 'tls_(ssl)', 'zlib']
},
{
  name: 'child_process',
  before: ['console', 'events', 'module', 'process', 'stream', 'util'],
  after: ['cluster', 'domain', 'http', 'https', 'net', 'readline', 'repl', 'tls_(ssl)', 'tty', 'zlib']
},

So, this worked pretty well. It shows all the modules and in which order I should read them so that I'd understand any references I ran across. To make it even simpler, below is the list I used while navigating the Node API docs. I'm happy to say, I've now gone through all of it (except a few that I could see were not essential at this time) and understood it. Hopefully, this list will help you if you decide to do the same thing.

Cheatsheet

*Note: I just listed the count of dependent modules so I could see if it I'd limit myself by skipping one.

  1. module (after: 28)
  2. querystring (after: 0)
  3. assert (after: 0)
  4. console (after: 26)
  5. os (after: 1)
  6. url (after: 5)
  7. path (after: 0)
  8. dns (after: 0)
  9. debugger (after: 0)
  10. timers (after: 2)
  11. buffer (after: 2)
  12. addons (after: 0) Wait until you're bored with Node and want to write C++ to do this one.
  13. util (after: 19)
  14. punycode (after: 0) Wait until you need it to learn this one.
  15. stringdecoder (after: 0)
  16. events (after: 17)
  17. vm (after: 0)
  18. stream (after: 15) Just do the first part. The API for Stream Implementors can wait until you need to write your own.
  19. dgram (after: 0) Nothing depends on this, so wait until you need it.
  20. process (after: 14)
  21. fs (after: 5)
  22. child_process (after: 10)
  23. global (after: 0)
  24. net (after: 9)
  25. crypto (after: 0)
  26. repl (after: 0)
  27. tty (after: 1)
  28. readline (after: 0)
  29. tls_(ssl) (after: 1)
  30. http (after: 4)
  31. cluster (after: 0)
  32. zlib (after: 0)
  33. https (after: 0)
  34. domain (after: 0)

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.

Monday, May 26, 2014

Willy

I've been working on an assertion library this weekend called Willy.  The goal is to provide a very natural way to write tests.  Chai, Should, and Jasmine are pretty close, but still feel a bit awkward.  Willy provides for tests like:

will(foo).be(bar);
will(foo).have(['a', 'b', 'c']);

Apparently, Peter deHaan from Mozilla thinks it's cool.

Friday, May 23, 2014

Hello, Mocha

Apologies, but I've been writing more code than blogs recently.  My attention has been focused on Node recently and I've done some cool things: my first npm package, custom build environments for Sublime Text 3 (JSHint and Node Inspector), and a bunch of stuff I can't think of right now.  Sure, I've been a crappy blogger, but I've been learning constantly.  Since I would rather be a badass JS developer than a badass blogger, that's OK.

For convenience, I've been adding notes to the README.md file in the projects on Github.  This is much easier than the whole blog thing.  But, for you, my imaginary reader, I'm going to attempt to copy the html here.

update: Blogger doesn't want to play nicely with the Markdown styles, so I suggest reading it here.

Learn Mocha

This is a simple project to learn about Mocha.

Notes

Set Up

Start by initializing npm.
npm init
Walk through the steps to get a basic package.json.
Add mocha to the package. Add package dependencies through the console for convenience.
npm install mocha --save-dev
This adds it to package.json under "devDependencies".
Set up an npm script in package.json to test using the installed Mocha.
"scripts": {
    "test": "node_modules/.bin/mocha"
},
Add test/test.js to your project. This is where Mocha looks for tests by default.
If no file is specified when calling mocha, all *.js files in the ./test directory will be run. You can make it search recursively through the test dir with --recursive.
Now, running this from the console will execute the test cases in ./test.
npm test
This executes the "test" defined in package.json's "scripts".

Writing Tests

This has just wired up Mocha so far, which is the testing framework. The test(s) need to specify an assertion library to use. You can use Node's or anything else that throws errors (ie. write your own).

Asynchronous Tests

To make a test async, use the following format.
it('should work asynchronously', function (done) {
    // do some assertions
    done();
});
If you're testing something that returns a promise, use
it('should work asynchronously', function () {
    return stuff().should.eventually.be(true);
});

Pending Test Cases

When you're not sure how to write the assertion for a test case, you can leave it out. This will show the test as "pending" when run.
it('is a pending test case');

Only

When you just want to run one suite or test, add only.
describe.only('only this suite will run', function () {
    it('should test stuff');
    it('should test other stuff');
});

Specify a Reporter

You just get the dot-matrix reporter by default. You can specify others with --reporter foo. Add this to the package.json "test" entry. You can see the available reporters with
./node_modules/.bin/mocha --reporters

Watch Files for Changes

--watch watches for changings to the test file and any .js file in cwd. This is sweet.

Using a Makefile

According to Mocha's best practices, it's a good idea to "add a make test target to your Makefile". I'm not in the habit of providing a Makefile, but it's not that bad.
# The name of the file make will try to generate.
# If "test" already exists, make will not run the
# "recipe" for it.
test:
    # This is a "recipe", the commands used to create
    # the file "test".
    ./node_modules/.bin/mocha --reporter nyan

# Indicate that "test" is not a file to be created,
# but a task to execute.  This means it will always
# run the "recipe", even if "test" already exists.
.PHONY: test
From the terminal, you can now run make test and it will run the "recipe" specified above. For that matter, you can just run make since it's the only thing in there. (make ref)

References