NODEJS

Introducción

Nos permite ejecutar JavaScript fuera del navegador. Fue concevido para ejecutar I/O asíncrono (se ejecuta una tarea y cuando ésta termina, se ejecuta una función callback).

Instalamos node:

$ yaourt -S nodejs

y lo ejecutamos:

$ node

Tenemos las variables accesibles glboalmente console y process:

> console
{...}
> process
{...}

Podemos salir:

> process.exit(0)

Podemos ver los argumentos con los que se llamó:

> process.argv

Advertencia

document y alert no están en el entorno de node.

Módulos

Se basan en CommonJS (usando require):

> require(<path>)

en donde <path> puede ser una ruta absoluta o relativa. Si es un nombre, se buscará el módulo en:

  • node_modules/

Los módulos se pueden instalar mediante npm. Los modulos se pueden instalar localmente:

$ npm install <nombre>

o globalmente:

$ npm install -g <nombre>

Si la carpeta contiene el fichero package.json, instalará todas las dependencias del programa.

Ejemplo en que creamos nuestro nuevo módulo

Contenido de main.js:

var garble = require("./garble");

// Index 2 holds the first actual command line argument
var argument = process.argv[2];

console.log(garble(argument));

Contenido de garble.js:

module.exports = function(string) {
  return string.split("").map(function(ch) {
    return String.fromCharCode(ch.charCodeAt(0) + 5);
  }).join("");
};

Y se ejecuta:

$ node main.js JavaScript
Of{fXhwnuy

require(“fs”)

Se usa para interactuar con el sistema de ficheros. Normalmente vienen en dos variantes: asíncrona y síncrona.

Asíncronas

Por ejemplo, para leer un fichero:

var fs = require("fs");
fs.readFile("file.txt", "utf8", function(error, text) {
  if (error)
    throw error;
  console.log("The file contained:", text);
});

Para leer ficheros como si fueran binarios:

var fs = require("fs");
fs.readFile("file.txt", function(error, buffer) {
  if (error)
    throw error;
  console.log("The file contained", buffer.length, "bytes.",
              "The first byte is:", buffer[0]);
});

Síncronas

Leer un fichero de texto de forma síncrona:

var fs = require("fs");
console.log(fs.readFileSync("file.txt", "utf8"));

Mientras ocurre esta acción, el programa estará parado por completo.

require(“http”)

Se usa para hacer servidor HTTP. Por ejemplo:

var http = require("http");
var server = http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/html"});
  response.write("<h1>Hello!</h1><p>You asked for <code>" +
                 request.url + "</code></p>");
  response.end();
});
server.listen(8000);

El cliente apuntará a http://localhost:8000/hello para recibir el contenido.

La función que se pasa como argumento a createServer, se ejecuta siempre que un cliente hace una petición al servidor.

Por otro lado:

  • request representa petición.
  • response representa la respuesta.

La respuesta va típicamente como:

response.writeHead(<status>, <header>)
response.write(...)
...
response.write(...)
response.end(...)

Por último, server.listen “arranca el servidor” y comienza a esperar por peticiones.

Este módulo también proporciona la función request que permite comportarse como un cliente:

var http = require("http");
var request = http.request({
  hostname: "eloquentjavascript.net",
  path: "/20_node.html",
  method: "GET",
  headers: {Accept: "text/html"}
}, function(response) {
  console.log("Server responded with status code",
              response.statusCode);
});
request.end();

require(“https”)

Para comunicaciones seguras.

Streams

Los streams pueden ser de lectura o de escritura. Todos los de escritura tendrán los métodos:

  • write: escribe datos en el stream.
  • end: cierra el stream.

Como argumentos a estos métodos, se podrá pasar:

  • Una cadena o un Buffer.
  • Un callback opcional (una vez haya terminado la acción).

Por ejemplo, con ficheros:

> var fs = require('fs')
undefined
> var fp = fs.createWriteStream('prueba.txt', 'utf-8')
undefined
> fp.write("Hola")
true
> fp.write(" José")
true
> fp.end("\n")
undefined

Desde el punto de vista del servidor HTTP:

  • La variable request será de lectura.
  • La variable response será de escritura.

Desde el punto de vista del cliente HTTP:

  • La variable request es de escritura.
  • La variable response es de lectura.

Eventos

En nodejs, los objetos que emiten eventos, tienen un método llamado on:

<object>.on( <nombre_del_evento>, <callback> )

Los streams de lectura, tienen los eventos:

  • ‘data’
  • ‘end’
  • ‘open’
  • ‘error’

Para crear un stream de lectura, creamos el fichero:

> var fs = require('fs')
> var readStream  = fs.createReadStream('prueba.txt', 'utf-8')
> readStream.pipe( process.stdout )

O en un fichero copy.js:

var fs = require('fs');
console.log(process.argv[2], '->', process.argv[3]);

var readStream = fs.createReadStream(process.argv[2]);
var writeStream = fs.createWriteStream(process.argv[3]);

readStream.on('data', function (chunk) {
  writeStream.write(chunk);
});

readStream.on('end', function () {
  writeStream.end();
});

//Some basic error handling
readStream.on('error', function (err) {
  console.log("ERROR", err);
});

writeStream.on('error', function (err) {
  console.log("ERROR", err);
});

y ejecutamos:

$ node copy.js file1.txt file2.txt

Nota

cuando chunk es un binary buffer, podemos convertirlo a una cadena utf-8 mediante toString().