Concepto de programación funcional
CPS: Continuation-passing Style
¡También conocidas como callbacks!
El estado pasa como parámetros y clausuras
var net = require('net');
var port = 1702;
var server = net.createServer(function(connection) {
console.log('Connection to %s open', port);
connection.write('Hello?\r\n');
connection.on('data', function(data) {
if (String(data).trim() != 'hello) {
connection.write('ERROR\r\n');
} else {
connection.end('world\r\n');
console.log('Connection to %s closed', port);
}
});
});
server.listen(port);
Continuaciones en amarillo
var net = require('net');
var port = 1702;
var server = net.createServer(function(connection) {
console.log('Connection open');
connection.write('Hello?\r\n');
connection.on('data', function(data) {
if (String(data).trim() != 'hello') {
connection.write('ERROR\r\n');
} else {
connection.end('world\r\n');
console.log('connection closed');
}
});
});
server.listen(port);
Librería para ejecución asíncrona
Basada en continuaciones
async.series()
: corre las funciones una tras otraasync.parallel()
: corre las funciones a la vezasync.waterfall()
: pasa el resultado de una a otra
Fuente: async
Ejemplo:
// an example using an object instead of an array async.series({ one: function(callback){ setTimeout(function(){ callback(null, 1); }, 200); }, two: function(callback){ setTimeout(function(){ callback(null, 2); }, 100); } }, function(err, results) { console.log('Results: %j', results); });Fuente: async
Usa el módulo async para leer una serie de valores
y sumarlos
¡Cuidado con las clausuras!
Hay que leer todos los ficheros:
Para cada uno debe parsear el JSON,
leer el campo "Debt",
y acumular todos los valores
Lectura de un JSON:
var request = require('request'); var url = 'http://stats.mediasmart.es/bulk/test-2014/account-01.json'; request(file, function(err,res,body) { if (!err && res.statusCode==200) { body = JSON.parse(body); console.log('Debt: %s', body.Debt); } });
Función que devuelve una función (que lee el JSON):
var request = require('request'); function getDebtReader(url) { return function(callback) { request(file, function(error, result, body) { if (error || result.statusCode != 200) { return callback('Could not read ' + url); } body = JSON.parse(body); return callback(null, body.Debt); }); }; }
'use strict'; var client = require('./lib/client.js'); var options = { port: 11311, host: 'localhost' }; var client = new client.Client(options, function(error) { console.assert(!error, 'Could not open connection'); var key = 'testing'; var value = 'real value'; client.set(key, value, function(error, result) { console.assert(!error, 'Error setting key'); console.assert(result, 'Could not set key'); client.get(key, function(error, result) { console.assert(!error, 'Error getting key'); console.assert(result == value, 'Invalid get key'); client.delete(key, function(error, result) { console.assert(!error, 'Error deleting key'); console.assert(result, 'Could not delete key'); client.close(function(error) { console.assert(!error, 'Error closing client'); }); }); }); }); });
Fuente: simplecached
La temida pirámide de callbacks
Infinitas continuaciones anidadas
Abuso de lambdas (funciones anónimas)
Difícil de seguir, depurar y refactorizar
Usar funciones con nombre
Crear un objeto con funciones con nombre
Las clausuras se convierten en atributos
Usar async: async.waterfall()
Usar eventos: EventEmitter
Revisar la pirámide de callbacks
Código original: servidor de sockets
Convertir a objeto con atributos
No dejar dos callbacks anidadas
var net = require('net');
var port = 1702;
var server = net.createServer(function(connection) {
console.log('Connection to %s open', port);
connection.write('Hello?\r\n');
connection.on('data', function(data) {
if (String(data).trim() != 'hello) {
connection.write('ERROR\r\n');
} else {
connection.end('world\r\n');
console.log('Connection to %s closed', port);
}
});
});
server.listen(port);
Continuaciones en amarillo
Revisar la pirámide de callbacks
Código original: test de simplecached
Convertir a objeto con atributos
No dejar más de dos callbacks anidadas