JavaScript Hell
Como sobrevivir al infierno del JavaScript Asíncrono


JavaScript Hell
¿Por que NodeJS y JS?


- Excelentes benchmark y reviews
- Características técnicas interesantes
-
Single Thread y asincrono
-
- Experiencia con lenguajes flexibles
- Popularidad creciente
- ... Odiaba la sintaxis de Python
JavaScript Hell
Single Threading


- Lavar ropa
- Lavar losa
-
Preparar cena
- Preparar pollo
- Preparar arroz
- Preparar bebidas
- Pedir el domicilio del mercado

Thread
JavaScript Hell
Single Threading


Poner ropa en lavadora

Colgar ropa
Poner losa en lavatrastes
Organizar losa
Servir Arroz
Poner a cocinar arroz
Servir Pollo
Poner pollo en horno

JavaScript Hell
Multi Threading


Poner ropa en lavadora

Colgar ropa
Poner losa en lavatrastes
Organizar losa
Servir Pollo
Poner pollo en horno






JavaScript Hell
Single Threading y Asincronismo


- Lavar ropa
- Lavar losa
-
Preparar cena
- Preparar pollo
- Preparar arroz
- Preparar bebidas
- Pedir el domicilio del mercado

JavaScript Hell
Single Threading y Asincronismo




Poner ropa en lavadora
Colgar ropa
Poner losa en lavatrastes
Organizar losa
Poner pollo en horno
Servir Arroz
Poner a cocinar arroz
Preparar Bebidas
Pedir Domicilio
Servir Pollo
Servir toda la comida
Revisa lista
Recibir Domicilio
Organizar mercado
JavaScript Hell



JavaScript Hell
Single Threading y Asincronismo


- Alto rendimiento
- Bajo consumo de recursos
- Resistente a fallos
JavaScript Hell
Single Threading y Asincronismo
(El problema)


LA PRACTICA ES UNA PESADILLA!!!

JavaScript Hell
JS Asincrono


/**
* @params ropaSucia La ropa sucia
* @params {function} cb
*/
function ponerRopaEnLavadora(ropaSucia, cb){
lavar(ropaSucia, function(err, ropaLimpia){
if(err){
return cb(err);
}
cb(null, {ropaLimpia:ropaLimpia});
});
}JavaScript Hell
JS Asincrono


/**
* @params ropaSucia
* @params losaSucia
* @params insumosCena
* @params telefonoDomiciliario
* @params {function} cb
*/
function realizarTareas(ropaSucia, losaSucia, insumosCena, telefonoDomiciliario, cb){
let resultado = {};
ponerRopaEnLavadora(ropaSucia, function(err, ropaLimpia){
if(err){
return cb(err);
}
colgarRopa(ropaLimpia, function(err, ropaSeca){
if(err){
return cb(err);
}
resultado.ropaSeca = ropaSeca;
ponerLosaEnLavatrastes(losaSucia, function(err, losaLimpia){
if(err){
return cb(err);
}
organizarLosa(losaLimpia, function(err){
if(err){
return cb(err);
}
prepararPollo(insumosCena.pollo, function(err, pollo){
if(err){
return cb(err);
}
let insumosPreparados = {};
insumosPreparados.pollo = pollo;
prepararArroz(insumosCena.arroz, function(err, arrozFrito){
if(err){
return cb(err);
}
insumosPreparados.arroz = arrozFrito;
prepararBebidas(insumosCena.mora, function(err, jugoDeMora){
if(err){
return cb(err);
}
insumosPreparados.jugo = jugoDeMora;
resultado.comidaPreparada = insumosPreparados;
pedirDomicilio(telefonoDomiciliario, function(err, mercado){
if(err){
return cb(err);
}
cb(null, resultado);
});
});
});
});
});
});
});
});
}JavaScript Hell
Callback Hell






JavaScript Hell
Callback Hell


/**
* @params ropaSucia
* @params losaSucia
* @params insumosCena
* @params telefonoDomiciliario
* @params {function} cb
*/
function realizarTareas(ropaSucia, losaSucia, insumosCena, telefonoDomiciliario, cb){
let resultado = {};
let operacionesPendientes = 4;
function verificarFinal(){
if(--operacionesPendientes > 0) {
return;
}
cb(null, resultado);
}
ponerRopaEnLavadora(ropaSucia, function(err, ropaLimpia){
if(err){
return cb(err);
}
colgarRopa(ropaLimpia, function(err, ropaSeca){
if(err){
return cb(err);
}
resultado.ropaSeca = ropaSeca;
verificarFinal();
});
});
ponerLosaEnLavatrastes(losaSucia, function(err, losaLimpia){
if(err){
return cb(err);
}
organizarLosa(losaLimpia, function(err){
if(err){
return cb(err);
}
verificarFinal();
});
});
let cantInsumos = 3, insumosPreparados={};
function verificarServirCena(err, insumoPreparado, tipoInsumo){
if(err){
cb(err);
}
insumosPreparados[tipoInsumo] = insumoPreparado;
if(--cantInsumos > 0){
return;
}
resultado.comidaPreparada = insumosPreparados;
verificarFinal();
}
prepararPollo(insumosCena.pollo, function(err, pollo){
verificarServirCena(err, pollo, "pollo");
});
prepararArroz(insumosCena.arroz, function(err, arrozFrito){
verificarServirCena(err, arrozFrito, "arroz");
});
prepararBebidas(insumosCena.mora, function(err, jugoDeMora){
verificarServirCena(err, jugoDeMora, "jugo");
});
pedirDomicilio(telefonoDomiciliario, function(err, mercado){
if(err){
return cb(err);
}
verificarFinal();
});
}JavaScript Hell
caolan / Async


const async = require("async");
...
function lavarRopa(ropaSucia, cb){
async.waterfall([
function(cb){
ponerRopaEnLavadora(ropaSucia, cb);
},
function(ropaLimpia, cb){
colgarRopa(ropaLimpia, cb);
}
], function(err, ropaSeca){
if(err) {
// do something
return cb(err);
}
cb(null, ropaSeca);
});
}
... // lavarLosa
function prepararCena(insumosCena, cb){
async.parallel({
pollo: function(cb){
prepararPollo(insumosCena.pollo, cb);
},
arrozFrito: function(cb){
prepararArroz(insumosCena.arroz, cb);
},
jugoDeMora: function(cb){
prepararBebidas(insumosCena.mora, cb);
}
}, function(err, insumosPreparados){
/*
* insumosPreparados = {
* pollo: new PolloHorneado(),
* arrozFrito: new Arroz(),
* jugoDeMora: new Jugo()
* }
*/
if(err) {
// do something
return cb(err);
}
cb(null, insumosPreparados);
});
}
/**
* @params ropaSucia
* @params losaSucia
* @params insumosCena
* @params telefonoDomiciliario
* @params {function} cb
*/
function realizarTareas(ropaSucia, losaSucia, insumosCena, telefonoDomiciliario, cb){
async.parallel({
ropaSeca: function(cb){
lavarRopa(ropaSucia, cb);
},
lavarLosa: function(cb){
lavarLosa(losaSucia, cb);
},
comidaPreparada: function(cb){
prepararCena(insumosCena, cb);
},
mercado: function(cb){
pedirDomicilio(telefonoDomiciliario, cb);
}
}, function(err, result){
if(err) {
// do something
return cb(err);
}
cb(null, result);
})
}JavaScript Hell
Promises (Promesas)


function lavarRopa(ropaSucia){
return ponerRopaEnLavadora(ropaSucia)
.then(function(ropaLimpia){
// esto se puede simplificar
return colgarRopa(ropaLimpia);
})
.then(function(err, ropaSeca){ //Este then sobra
return ropaSeca;
});
}
... // lavarLosa
function prepararCena(insumosCena){
return Promise.all([
prepararPollo(insumosCena.pollo),
prepararArroz(insumosCena.arroz),
prepararBebidas(insumosCena.mora)
]).then(function(results){ // Array
const insumosPreparados = {
pollo: results[0],
arrozFrito: results[1],
jugoDeMora: results[2]
}
return insumosPreparados;
});
}
/**
* @params ropaSucia
* @params losaSucia
* @params insumosCena
* @params telefonoDomiciliario
*/
function realizarTareas(ropaSucia, losaSucia, insumosCena, telefonoDomiciliario){
return Promise.all([
lavarRopa(ropaSucia),
lavarLosa(losaSucia),
prepararCena(insumosCena),
pedirDomicilio(telefonoDomiciliario),
}).then(function(results){
results = {
ropaSeca: results[0],
lavarLosa: results[1],
comidaPreparada: results[2],
mercado: results[3],
}
return results;
})
.catch(function(err){
//do somenthing
console.err(err);
});
}JavaScript Hell
async / await (ES7)


async function lavarRopa(ropaSucia){
const ropaLimpia = await ponerRopaEnLavadora(ropaSucia);
const ropaSeca = await colgarRopa(ropaLimpia);
return ropaSeca;
// return await colgarRopa(await ponerRopaEnLavadora(ropaSucia));
}
... // lavarLosa
async function prepararCena(insumosCena){
let insumosPreparados = await Promise.all([
prepararPollo(insumosCena.pollo),
prepararArroz(insumosCena.arroz),
prepararBebidas(insumosCena.mora)
]);
return {
pollo: results[0],
arrozFrito: results[1],
jugoDeMora: results[2]
}
}
/**
* @params ropaSucia
* @params losaSucia
* @params insumosCena
* @params telefonoDomiciliario
*/
async function realizarTareas(ropaSucia, losaSucia, insumosCena, telefonoDomiciliario){
try{
let results = await Promise.all([
lavarRopa(ropaSucia),
lavarLosa(losaSucia),
prepararCena(insumosCena),
pedirDomicilio(telefonoDomiciliario),
});
return {
ropaSeca: results[0],
lavarLosa: results[1],
comidaPreparada: results[2],
mercado: results[3],
}
} catch(err) {
//do somenthing
console.err(err);
}
}JavaScript Hell
async / await (ES7): Soporte



JavaScript Hell
Epilogo


JavaScript Hell
Como sobrevivir al infierno del JavaScript Asíncrono


JavaScript Hell
By CucutaJS
JavaScript Hell
- 85