Sergeant.js

Some might say javascript encourages nesting, for example;

var greetDeeplyCurried = function(greeting) {
  return function(separator) {
    return function(emphasis) {
      return function(name) {
        console.log(greeting + separator + name + emphasis);
      };
    };
  };
};

Personally, I don’t like anonymous functions. They make it harder to debug. If you do use an anonymous function, please still give it a name. note the for

var bar = function () {…}

, the function is still anonymous. You should either write

var foo = function foo () {}

or

function foo (){}; var bar = foo;
  1. I don’t like creating function inside other functions, since I don’t know how many time the wrapping function will be called. Simply define two function and let the wrapping called the internal.

Nesting function is the lazy-solution to handle Javascript’s scope issue, as function don’t really hold a scope on their own one might find it easier to have all the scope nestled together so for sure you’d know, which scope is being used.

I would resolve that using bind, call and apply to determine the specific scope I would like my function to run. Generally I would avoid outside-the-function scope variables – each function should use only what is passed into it, and with the use of bind you can send parameters from different sources: in this example

myButton.onclick = foo.bind({},myVariable)

myButtons will have two parameters – myVariable and the onClickEvent, both coming from different sources.

That’s being said, My server-side has a lot of sequential asynchronous operations – load a topic and use its data to load the community and the member and then makes changes, write them and send the result to the client side.

I suggest a Sargent to manage our tasks on our behalf.

sergeant({ topic: { table: db.topic,
                         data: userNewTopic,
                         after: sergeant.validate }, 
           member: { table: membership,
                     load:{ userId: authUser.id }, 
                     before:getTopicCommunityId,
                     after: sergeant.isSuccess } ,
           savedTopic: { table: db.topic, 
                         before:prepareForSaving,
                         after: sergeant.isSuccess },
           finalize: { json:true }},
           “topic,member,savedTopic, finalize”,  callback);

or

sergeant({ map of tasks },
           [ordered list of task name], methodToRunWhenDone);

A task has the following properties

  • table – a node-ORM object
  • load – either a object-id value or a node-ROM compliant map of properties
  • multiple – if the object exists, load will assume multiple results. Multiple can be a node-ROM compliant list of properties such as order, limit, order, and groupBy
  • data – data placeholder to be passed on or used by save
  • save – boolean flag. When save=true, data will be saved. The repository[taskName] will then store the save operation output.
  • before – function to be called before commencing the task’s main operation.
  • after -function to be called once the task’s main operation is completed
  • json – will run toJSON() function on items in the repository

before/after functions may return the following values

  • true/ undefined – continue operation as normal
  • false – the main operation will be skipped or discarded. If before return false, after will not  run as well
  • Error – sergeant will stop its operation and call methodToRunWhenDown(error)

load overrides data (so data acts as default value until load is pre-populated)

A Task with load but save=true will throw an error  before any task starts.

[ordered list of task name] can either be an array of tasks-names or a comma-separated string.

The before and after functions’ parameters are (repository, taskMap, currentTaskName)

json runs after the main operation but before post. Its value can be one of the following

  • true – will json-convert the entire repository
  • [] – (empty array) will json-convert only the current task result. if there’s no data or load properties for the task it will exit before running
  • [taskNames] (array of strings or comma-separated string) – will json-convert the specific tasks output. json is agnostic whether the task have run or not
  • undefined/false – won’t try to json-convert

 

If repository[taskName] is an array, json returns an array of objects, each was json-converted.

A good practice will be to run post the last json and delete any unnecessary temporary repository elements.

so in conclusion, Sergeant.js is used to run a list of db-related tasks (which seems to apply to most of my server-side methods) in a sequential order, thus saving the need to nest your operations in an unreadable fashion.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: