In my last post I covered a basic frhttp route with a couple of ‘when’ blocks and a render function. In this post I’ll go over the ‘when’ block in detail including some fields which aren’t used that often but can be super helpful.

Before we get started however, it’s worth noting that there’s been a fair bit of progress in frhttp since my last post. The current version, and the version that this post will discuss is 0.0.5. If you’ve npm installed an older version, please update to this version. It contains a number of new features and few bug fixes. A few of them are:

OPTIONS is now supported (in addition to GET, PUT, POST and DELETE)

The writer object now allows you to write an entire file to the client with the writeFile function

Lots more samples

when, the workhorse of your routes

Most of the heavy lifting of any route that’s not completely trivial will be done by ‘when’ blocks. These blocks have a single required parameter and several optional ones. They are also where most errors will occur so we’ve made efforts to make errors very friendly and more importantly useful in debugging. We’ll start by taking a look at each parameter in detail, then discuss error handing. You can always find an up to date discussion of any ‘when’ field in the github wiki for the project.

{

fn : function(produce, input) { produce.done()}, /* required */

enter: function(input) { return input; }, /* not required */

exit: function(output) { return output; }, /* not required */ name : 'a name', /* not required */

params : [], /* not required */

produces : [], /* not required */

takeMany: false /* not required */

triggerOn : [], /* not required */

}

fn, what would we do without you?

fn is the only required parameter in the when block. It’s the function that you want executed when (no pun intended) the block runs. The function signature looks like this:

function(produce, input)

The produce object provides 3 methods you can use to generate output from your when block. These are:

value — value takes a name and a value, which is pretty self explanitory.

error — error takes an http error code and a description. You can return 500, or whatever error you choose, and provide a brief description of what went wrong.

done — you must call this when you’re finished producing values.

The input object contains all the parameters you requested in your params field (we’ll see that in a moment). If your param block looked like

['demo', 'zumba']

Your input might look like:

{

demo: 5,

zumba: 'yes'

}

enter, you shall not (maybe.)

The enter parameter can be used to modify inputs before executing your fn or you can use it to act as an advanced filter to prevent the fn from being executed. Suppose you have an fn that produces a sqrt, but (for non-error reasons) sometimes the incoming value can be negative. Here’s an example of using an enter function as a filter in this case:

function (input) {

if (input.testValue < 0) {

return undefined;

}

return input;

}

Notice that we return undefined if the testValue is negative. A return value of undefined (or any falsy value) lets the system know that it shouldn’t continue to run the when block.

exit, in case of emergency

The exit parameter can be used to modify the output or suppress it. The function takes one object that looks like this:

{

name: 'anOutput',

value: 'the value'

}

You should return this exact format, though obviously you can change the values for either name or value.

name, what’s in a name?

While optional, name is highly recommended as it provides very nice error messages.

params, the simple bare necessities

The params field is an array that specifies what values need to be available before your fn can be run. Your block will never be executed until all of these are available. Depending on other options, your block may be executed any time one or more of these change once all of them have at least an initial value. It’s very important that fn not operate on any values other than those declared in params. That’s what’s going to keep our functions pure and allow us to easily debug errors even if they occur later in production.

produces, making a dent in the universe (or route)

The produces field is an array of strings that specify the names of the values you can produce. If you attempt to produce something you haven’t declared, an error is logged to the console and the value is thrown away.

takeMany, mine, mine, mine

The takeMany field tells the system that this block should be executed any time any field specified in the params field changes once each of those field has an initial value. This is useful for, among other things, recursive calls or aggregation calls.

triggerOn, are you ignoring me?

The triggerOn field is used in conjunction with the takeMany field. Recall that earlier we talked about the possibility that a when block could be executed multiple times. The triggerOn field tells the system that the block should only execute when one of the fields specified in the triggerOn changes. If you omit this field and set takeMany, once each params field has an initial value, your block will re-execute any time any value you’ve specified in the params field changes. You can see a sample of how this can be used in the db.simulation.js example in the samples folder of the project.

Error handling. This is serious business.

If you’ve written a decent amount of Node.js code and especially Connect/Express style apps, then you’ve been here:

Because the callback stack loses history, you have no idea what happened, and if it starts happening in production you’re scrambling. You can try to keep the server restarted with pm2 or forever, but that’s not a solution, it’s a bandaid.

This is an area where frhttp really shines. If you’ve written your when blocks properly and kept your functions pure (only using your inputs and not other data) the errors you get from frhttp will be very useful in finding the problem even in production. Let’s take a sample (you can also find this in the samples directory of the project). Here’s a route that will throw an exception on purpose.

server.GET('/samples/uncaught.exception').onValue(function (path) {

path.inject({

demo: 'a value'

}).when({

name: 'Crashes On Purpose',

params: ['demo'],

fn: function(produce, input) {

input.crashNow(); // oops there's no crashNow function.

produce.done();

}

}).render({

params: [],

fn: function (writer) {

writer.writeBody('Never going to get here...!');

}

})

});

When we execute this route, 5oo error will be reported to the browser, and the following will be logged to the console:

ERROR: function (Crashes On Purpose) threw an exception (TypeError: Object #<Object> has no method ‘crashNow’) on input: {

“internal:__ready”: 1,

“demo”: “a value”

}

Stack Trace: TypeError: Object #<Object> has no method ‘crashNow’

at server.GET.onValue.path.inject.when.fn (/*/frhttp/samples/uncaught.exception.js:16:11)

at baconTemplate.onValue.runner (/*/frhttp/lib/routeExecutor.js:102:5)

at /*/frhttp/lib/routeExecutor.js:116:6

at process._tickCallback (node.js:415:13)

[note that I’ve shortened the paths for easier illustration]

I’ve bolded the interesting parts of this error. Notice that our exception was caught by the system, and more importantly it told us the exact input that caused the exception. Once we have the input, only the top of the stack matters because it lets us know exactly where to look.

That’s all for now…

Next time we’ll examine the render block and injection. If you want to play with frhttp you can check out the repo on GitHub or try it out via npm like so:

npm install frhttp

If you find an issue or have a question, open an issue on GitHub or give me a shout on twitter @ayasin.