Asincronía en Node.js

E/S sin bloqueo

Una de las mayores ventajas de usar Node.js sobre Python o Ruby es que Node tiene un mecanismo de E/S sin bloqueo. Para ilustrar esto, déjame usar un ejemplo de una línea en una cafetería Starbucks. Supongamos que cada persona que hace cola para tomar una copa es una tarea, y todo lo que hay detrás del mostrador (cajero, caja registradora, barista) es un servidor o una aplicación de servidor. Cuando pedimos una taza de café de goteo regular, como Pike, o té caliente, como Earl Grey, el barista lo prepara. Toda la fila espera mientras se prepara esa bebida y se le cobra a la persona la cantidad correspondiente.

Asincronía en Node.js

Eso sí, sabemos que este tipo de bebidas son fáciles de hacer; solo vierte el líquido y listo. Pero, ¿qué pasa con esos elegantes choco-mocha-frappe-latte-soy-decafs? ¿Qué pasa si todos en la fila deciden pedir estas bebidas que consumen mucho tiempo? La línea se detendrá por cada orden, y crecerá más y más. El gerente de la cafetería tendrá que agregar más registros y poner a trabajar a más baristas (o incluso estar detrás del registro él mismo). Esto no es bueno, ¿verdad? Pero así es como funcionan prácticamente todas las tecnologías del lado del servidor, excepto Node. Node es como un Starbucks real. Cuando pides algo, el barista le grita la orden al otro empleado y te vas de la caja registradora. Otra persona da su pedido mientras esperas tu revelación de última generación en un vaso de papel. La línea se mueve, los procesos se ejecutan de forma asíncrona y sin bloquear la cola por espera.

Esta es la razón por la que Node.js supera a todo lo demás (excepto quizás a C/C++ de bajo nivel) en términos de rendimiento y escalabilidad. Con Node, simplemente no necesita tantas CPU y servidores para manejar la carga.

Forma de codificación asíncrona

La asincronía requiere una forma diferente de pensar para los programadores familiarizados con Python, PHP, C o Ruby. Es fácil introducir un error sin querer si se olvida finalizar la ejecución del código con un retorno adecuado. expresión.

Aquí hay un ejemplo simple que ilustra este escenario:

var test = function (callback) {
  return callback();  
  console.log('test') //shouldn't be printed
}

var test2 = function(callback){
  callback();
  console.log('test2') //printed 3rd
}

test(function(){
  console.log('callback1') //printed first
  test2(function(){
  console.log('callback2') //printed 2nd
  })
});

Si no usamos return callback() y solo usamos callback(), se imprimirá nuestra cadena test2 (la prueba no se imprime).

callback1
callback2
tes2

Por diversión he añadido un setTimeout() retraso para la cadena callback2, y ahora el orden ha cambiado:

var test = function (callback) {
  return callback();  
  console.log('test') //shouldn't be printed
}

var test2 = function(callback){
  callback();
  console.log('test2') //printed 2nd
}

test(function(){
  console.log('callback1') //printed first
  test2(function(){
    setTimeout(function(){
      console.log('callback2') //printed 3rd
    },100)
  })
});

Impresiones:

callback1
tes2
callback2

El último ejemplo ilustra que las dos funciones son independientes entre sí y se ejecutan en paralelo. La función más rápida terminará antes que la más lenta. Volviendo a nuestros ejemplos de Starbucks, es posible que obtenga su bebida más rápido que la otra persona que estaba frente a usted en la fila. ¡Mejor para las personas y mejor para los programas! :-)