permalink

0

Creando aplicaciones Node.js con TypeScript – Parte 2 #nodejs

Accediendo a la base de datos

Editamos el fichero db.ts y añadimos aquí el código que accede a nuestra base de datos MongoDB. Para ello, importamos el módulo de mongodb y creamos una instancia de la clase mongodb, establecemos la conexión con la base de datos y la abrimos:

import mongodb = module('mongodb');
var server = new mongodb.Server('localhost', 27017, {auto_reconnect: true}, {})
var db = new mongodb.Db('highscores', server);
db.open(function() {});

Una vez abierta la conexión, definimos una clase que describe los objetos que esperamos enviar/recibir de la colección “highscores”. Esta es una de las ventajas de utilizar TypeScript, que nos permite definir y trabajar con clases, e indicar el tipo de los parámetros de nuestras funciones.

export class Score {
    _id: string;
    user: string;
    score : number;
}

Ahora podremos definir las funciones que expone este módulo. Veremos que hay ciertos elementos nuevos con respecto a una definición en JavaScript.

export function getScores(callback: (scores: Score[]) => void) {

    db.collection('scores', function(error, scores_collection) {
        if(error) { console.error(error); return; }
        scores_collection.find({}).toArray(function(error, scoresobj) {
           if(error) { console.error(error); return; }
           callback(scoresobj);
        });
        
    });
}

La primera la vemos en los parámetros, estamos indicando que tendremos un callback, que será de tipo void (esto es, que no devuelve nada) la cual recibirá una lista de objetos de tipo Score (la clase que acabamos de definir). Este callback será la función anónima que acabamos de definir en el módulo index:

(scores) => {
        res.render('index', { title: 'Highscores', scores: scores })
}

El resto de una función es la típica que provee el módulo de mongoDB. Pero ya podemos ver la facilidad con la que podríamos cambiar el servidor al que nos conectamos o incluso el repositorio de datos…

Definiendo las vistas

Gracias a JadeJS podemos cambiar el aspecto de la UI de una forma muy sencilla. En nuestro caso sólo vamos a definir una vista en la que mostrar la lista de puntuaciones. Para ello creamos 2 ficheros: layout.jade para tener unos elementos comunes e index.jade para mostrar la lista:

layout.jade

!!!
html
  head
    title ImageBoard
    link(rel='stylesheet', href='http://cachedcommons.org/cache/960/0.0.0/stylesheets/960.css')
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    #header.container_12
      script(src='http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.min.js')
    #container.container_12!= body

index.jade
h1= title
p Welcome to #{title}

ul
- each score in scores
  li
    b= score.user + " " + score.score

index.jade

h1= title
p Welcome to #{title}

ul
- each score in scores
  li
    b= score.user + " " + score.score

No es intención de este artículo explicar cómo utilizar Jade, pero vemos que podemos recorrer de una forma muy sencilla una lista de elementos, en nuestro caso la clasificación de puntuaciones, y mostrarlas en una página.

Si desde SublimeText compilamos el fichero app.ts podremos ver cómo se generan todos los ficheros JavaScript que serán los que utilice nuestra aplicación. Gracias a la Build Definition que hemos creado anteriormente, no es necesario hacerlo por cada fichero .ts, sino que se hace automáticamente para todos los que necesitamos. Y ya podemos arrancar la aplicación:

node app.js

y abrimos un navegador para ver el resultado:

tuto_3

Podemos ver que la página se renderiza correctamente pero no nos muestra ningún resultado, esto es normal puesto que no tenemos ningún registro en nuestra colección MongoDB. Vamos a hacer una página para insertar registros.

Añadiendo más funcionalidades

Siguiendo el mismo proceso que antes, lo primero que hacemos es modificar nuestro fichero de aplicación (app.ts) para añadir dos métodos nuevos, un GET que cargue un formulario y un POST para insertar los datos:

app.get('/scores/newscore', (req, res) => {
    routes.newscoreget(req, res);    
});

app.post('/scores/newscore', (req, res) => {
   routes.newscorepost(req, res);
});

Definimos los nuevos métodos en nuestro fichero index.ts:

export function newscoreget(req: express.ExpressServerRequest, res: express.ExpressServerResponse){
     res.render('newscore',{});   
};

export function newscorepost (req: express.ExpressServerRequest, res: express.ExpressServerResponse){
    var newscore = new db.Score()
    newscore.user = req.param('user');
    newscore.score = req.param('score');
     db.addScore(newscore, (r) => {
        res.redirect('/');
    });
};

Como vemos, el primero únicamente renderiza el formulario y es el segundo método el que llamará a nuestro módulo de acceso a datos. En este segundo método utilizamos un objeto de la clase Score que hemos definido en otro módulo, que será lo que pasemos como parámetro al método addScore. Veamos cómo implementamos este método:

export function addScore(newscore : Score, callback: (result: any)=> void){
    db.collection('scores', function(error, scores_collection) {
        if (error) { console.error(error); return; }
        scores_collection.insert({"user" : newscore.user, "score" : newscore.score },
            (error, result) => {
                if(error) { console.error(error); return; }
                callback(result);
            })
        });
}

Gracias a que utilizamos una clase de TypeScript, podemos ver sus propiedades cuando las necesitemos:

tuto_4

Y por último, creamos la vista newscore.jade con el formulario en el que añadimos el usuario y la puntuación:

form( method="post")
   div
       br
       div
           span.inputtitle User name :
           input(type="text", name="user")
       br
       div
           span.inputtitle Score :
           input(type="text", name="score")
       br
       #editScoreSubmit
           input.button(type="submit", value="Save Score")

Y modificamos nuestra vista principal para añadirle un botón que llame a nuestra recién creada vista:

h1= title
p Welcome to #{title}

ul
- each score in scores
  li
    b= score.user + " " + score.score
br
form( action="/scores/newscore/", method="get")
    div
        #newScoreSubmit
            input.button(type="submit", value="New Score")

Volvemos a compilar el fichero app.ts y arrancamos la aplicación, si todo ha ido bien ya podremos acceder al formulario para añadir puntuaciones:

tuto_5Y ver el resultado en la página principal:

tuto_6

RESUMIENDO

Este pequeño ejemplo nos ha servido para ver cómo se puede hacer una aplicación web con NodeJS y TypeScript con una buena estructura, el código bien organizado y siguiendo el patrón MVC. Esto nos permite que, si la aplicación es muy grande, el trabajo se pueda repartir entre diferentes personas/grupos de manera muy sencilla. Además, podemos tener definidos módulos de prueba (fakes) que simulen funcionalidades que no están desarrolladas.

Autor de éste Artículo

Pablo Bouzada, desarrollador especializado en .NET y otras tecnologías Microsoft. Consultor en Pasiona Consulting y divulgador tecnológico en Techdencias. Colaborador de programandonet.com y otros grupos de usuarios de España.

Twitter: @pbousan

Slideshare: http://www.slideshare.net/pbousan

GitHub: https://github.com/pbousan?tab=repositories