Coding and... stuff

4.07.2013

In javascript, callbacks are a complicated idea and for someone new to javascript, the idea causes significant confusion.

First - what is a callback?

A callback is the call that the system does in return when a process we started has yet to finish, and we need that process call to do something specific. Wikipedia gives a pretty good definition of this. We usually do a function that returns something in a synchronous way, for example

In this case, we just call the function "turnOnPC" and we wait for the function to finish processing, looking for areturn as to whether or not the pc turned on correctly or not. But, what happens if we have a slow or really old pc? Sitting and waiting won't be effective here.

Asynchronous programming

Asynchronous programming refers to the ability to call a function without the need of waiting for it to end. In javascript it's very common to use this. Javascript allows us to send functions as parameters to the functions... wait, what??In javascript functions behave a little bit differently than in other programming languages. For more information about functions in general, check out the MDN documentation. Back to our example

Usually we pass variables as arguments to other functions, which you can also easily do in js. In this case we are sending a function as an argument to "turnOnPc" and at the end of the function it calls back the function we sent with some parameters "callback()". In this particular case we are using a common pattern found in node.js where we always send the error variable as a first parameter and then all the other data variables as needed.In the trivial example of turning on a PC, imagine having to wait to go get a drink of water until your PC finished booting. Asyncronous calls allow you to go get a drink of water while your PC boots. We don't have to wait for "turnOnPc" to end, when "turnOnPc" ends it will call the function we sent it and then follow with the functionality necessary.

Callback Hell

Its very common to be entangled in several functions that needs a callback, lets look to our example expanded

To avoid long lists of nested callbacks, generate functions with names and don't send anonymous functions. Even better yet, use "promises" to do that.

Where i have seen them??!!

One of the most common uses for callbacks in javascript is calling AJAX or DOM events. In node.js usually it's used for complex calls, slow methods, or file/network access. Here is an easy example with jquery

In this case, we are binding the function to the click event of the element "element". You can read this as when the user clicks on "element" run this function. You are not necessarily on the screen doing nothing, but you are waiting for the event to happen to run the function while the page is still working without blocking the page.Another common example is ajax

Although jquery already uses promises, we can use this as an example. Here we are calling some service, and when that service responds we run the function inside "done"

Node.js uses callbacks for many things. ffor example, when we are loading a file we can do it synchronously or asynchronously. If we do it synchronously the thread will stop until the file is loaded completely which is not a good way to do it. But, if we do it asynchronously, other functions will run while the file ends loading

The function takes the file path and a callback. When the function finishes loading the file it calls the callback.

What happens with this?!!

"This" in javascript its the context in which we are currently running, in the browser. Without being inside a function specifically, the context is "window" which is the global object. When you are inside a callback, "this" can change. For example when you are listening for an event with jquery, "this" is the DOM element that you have listening to the event

5.28.2012

This time we will see how to deploy tour app in node.js to cloudno.de, there are other services also that do a great job like heroku or nodester but for this time we will use this one that i recommend, they helped me when i need it and you can create couchdb and redis databases if you needed, the service its in beta and free so its nice, very nice

Like all the other systems we have to install their cli or "command line interface", which its only an script to help us with the deployment, updates and everything else of our app in their systems

npm install cloudnode-cli -g

Or without the g if you want a local installation and not global

Ok, we have the cli installed, lets go to the page and create a new app, this will give us the subdomain url of the app and the github repository to upload it, also a user name and a key

With the cli installed, lets setup the user, this have to be done only once

What it does its clone the repository to your machine and create an entry code just to test the app, you can clone your app in cloud9ide.com and commit there

Every time you make a commit, the system in cloudnode will restart the app so you can see the new changes immediately, also it doesnt matter the port you put on your application since cloudnode will overwrite it

And thats it, you can see your app running in cloudnode with the url provided that will be something like <app name>.cloudno.de

First part on the file is loading a module, the modules are loaded with require, to understand more about require check this post, plus read the documentation about it

Besides just loading them, you can pass them parameters like

require('./routes/index')(app, log);

In this case we are passing some vars to the require module

Console

Also in the first program, we can see the console.log to print out information in the console, this is useful at debugging time or to show information to the user, check the documentation for more information about using the console, there are also different levels to show the information besides there are a lot of modules that extend the functionality, some print out in colors, prettify the information, etc.

Create a server

Besides creating a serve with the http module and tell the port and the ip to listen, we can create servers with other modules, one of the most common is express, to create it with express its simple:

var app = module.exports = express.createServer();

And then we can tell it in which port to listen

app.listen(3000);

You can pass the ip also, by default it takes the '0.0.0.0' which means everywhere

There are a lot of other modules to create servers, do a quick search in github or npm to find the one that suit you better, most of them follows the same pattern

Read and write files

For this we have a nice module called "fs" or filesystem, this module have everything needed for read, write, etc in files, links or directories

FS have the option to do the operations in async or sync way, as a good practice try to always do it async

Also you can use async.js to do it even more easy the async manipulation of files

Logging

In case you want to log information to a file for future references, you can use some modules for this, in the case of nomination we use "log.js" which is quite simple to use:

Log = require('log'),
log = new Log(),
fs = require('fs');

First we have to load the module and create an object which is the one that we are going to use in the app to log information, then we have to load fs, because we need to create the file were we are going to write

After we tell the level of logs the file will have, this should be changed depending on the configuration that we are going to use, we may want to have less level of log traces for production for example

After create the file lets add it to the stream and we just need to start logging information with different levels

Check the documentation for log.js, and also there are alot of modules to do logging, from manual stuff like the one we use here to others that are helpers or middleware for some frameworks like express/connect, etc, check more modules

Callbacks

Since we use alot of async in our node.js programs we end up using a lot of callbacks, callbacks are nothing more than where our function will return after doing its process, the convention for calling the callback its always return an error even if there isn't any and then the data

In this case you always check if there happened any error or not and its more easy to control the flow

Errors

We recommend to use the "new Error()" to send your errors instead of only one string, because new Error have information about the error, where did it happened, etc, this information its very important to debug the problems and have a better idea of what its going on in the code, with the string only we could lose some of that information, check the callback information above for more information about sending errors.

This time we will create a service that runs daily at some time to end the old nominations that are older than the actual date, for that we will need to add a new module, lets update our "package.json"

, "node-schedule" : "0.1.5"

And we run our command "npm install -d" to install the new dependency

Now lets first update our nominator.js controller to find old nominations

Get the id of the actual page, and then get the type on nomination the user is looking, then get the divider, erase the actual list, add again the divider, refresh and reload the nominations of that type

Good, easy, now lets update the routes to handle the request from small devices, lets update the file "routes/dashboard.js"

We are checking for tablet or mobile and if so lets redirect them to the mobile version, with this any user can see the mobile version by updating the url

We are just missing to update the strings in the jade files or js to i18 strings, lets give that task as a homework for all, any doubt on doing that let me know

Thats it for the mobile verions, we have a nice version now quite interesting, lets announce it everywhere now, if you can please help me with some bugs or new stuff for the application, i may be missing a nice feature.

Next time we will try to do a job to run it daily and close the nominations already passed and send notifications in facebook to the users.

After that we will move this to phonegap to make it native for different platforms :)

Now lets put the functionality for vote, delete and invite friends to the application

To start lets add a feature to the list of friends in the details of a nomination, when the user swipe left or right it will appear two buttons vote or delete, for that lets update "mscript.js", after add the user to the list we add (around line 150):

$('.users li').bind('swiperight swipeleft', swipe);

This will look for swipe function when the user swipe in any direction on any list item, lets add the function in the same file

Here we take the li as a reference, first erase the buttons if they exist already, then we create 2 buttons which have 2 clases, 1 for reference only and the other one to give them style and the position, for that lets add them to the css

Here we take the li from where we get called and the details div to get the nomination id

We create the user object with the details and we send it to the server to erase that user and we hide the buttons, after calling the server we erase the user from the list if everything went right or show the error if any

Same way as before we got the data from the li and details, post to the server the information and hide the buttons, on return from server, lets update the count of the votes or show if any error

Now we are only missing the "invite" functionality, for this one we are going to recycle the add friends screen, first lets update the template "dashboardm.jade", lets add a class to our invite button to look like this:

a.doinvite(href="#", data-icon="plus", class="ui-btn-right") Invite

Then lets add to out page with id "#addf" this button to the footer

a.invite(href="#", data-role="button", data-theme="b") Invite

And then lets initialize the button hidden in our css

.invite{
display: none;
}

Good now the script, lets update "#adduser" onclick to hide the button

In this case we are loading the list of friends from facebook and adding it to the list to use it later, this list will be loaded as soon as the user land on the page, for that lets call the function when jqm create the page:

First we show the msg that we are working, we retrieve the data from the form, we do a simple check and post it, show a message if any error, if the post goes without errors lets add the nomination to the mine list, then refresh the list so all the elements gets the styles, close the loading message and return to mine list

We have a new nomination, lets see the details, for this lets add to our lists that functionality, all the elements in the lists have the class "details" so lets use that

We bring the data for the selected nomination and we fill out the details page, depending on the type of the nomination is the buttons we show, we add the list of friends already nominated and we refresh the list, if any error we show the message to the user, in this function we also use a function to parse the date from Facebook called "setISO8601"