node medium catch await async node.js asynchronous async-await nonblocking

node.js - medium - node js await catch



Node.js vs Async/await in.net (4)

Ambos modelos son muy similares. Hay dos diferencias principales, una de las cuales se irá pronto (para alguna definición de "pronto").

Una diferencia es que Node.js es asíncrono de un solo subproceso, mientras que ASP.NET es de subproceso asíncrono. Esto significa que el código Node.js puede hacer algunas suposiciones simplificadoras, porque todo el código siempre se ejecuta en el mismo hilo exacto. Entonces, cuando su código ASP.NET esté en await , posiblemente podría reanudarse en un hilo diferente , y depende de usted evitar cosas como estado local de subprocesos.

Sin embargo, esta misma diferencia también es una fortaleza para ASP.NET, ya que significa que async ASP.NET puede escalar desde la caja hasta las capacidades completas de su servidor. Si considera, por ejemplo, una máquina de 8 núcleos, ASP.NET puede procesar (las partes síncronas de) 8 solicitudes simultáneamente. Si coloca Node.js en un servidor trucado, entonces es común que realmente ejecute 8 instancias separadas de Node.js y agregue algo como nginx o un simple equilibrador de carga personalizado que maneje las solicitudes de enrutamiento para ese servidor. Esto también significa que si desea que otros recursos se compartan en todo el servidor (por ejemplo, caché), también deberá moverlos fuera de proceso.

La otra gran diferencia es en realidad una diferencia en el lenguaje, no en la plataforma. El soporte asíncrono de JavaScript está limitado a las devoluciones de llamada y las promesas, e incluso si utiliza las mejores bibliotecas, igual terminará con un código realmente incómodo cuando haga algo no trivial. Por el contrario, el soporte async / await en C # / VB le permite escribir código asíncrono muy natural (y más importante aún, código asíncrono mantenible ).

Sin embargo, la diferencia de idioma está desapareciendo. La próxima revisión de JavaScript presentará los generadores, que (junto con una biblioteca de ayuda) harán que el código asíncrono en Node.js sea tan natural como lo es hoy usando async / await . Si desea jugar ahora con las cosas "próximamente", los generadores se agregaron en V8 3.19, que se convirtió en Node.js 0.11.2 (la rama inestable). Pasar --harmony o --harmony-generators para habilitar explícitamente el soporte del generador.

¿Puede alguien explicar / redirigirme, cuál es la diferencia entre el modelo asíncrono de Node.js (hilo no bloqueante) vs cualquier otro idioma, por ejemplo, la forma asíncrona de c # de manejar la E / S. Esto me parece que ambos son el mismo modelo. Amablemente sugiero


Con nodejs, todas las solicitudes van en la cola de eventos. El bucle de eventos de Node usa un único hilo para procesar elementos en la cola de eventos, hacer todo el trabajo que no es de IO y enviar a C ++ threadpool (usando devoluciones de llamada de javascript para administrar la asincronía) todo el trabajo vinculado a IO. Los hilos de C ++ luego agregan a la cola de eventos sus resultados.

Las diferencias con ASP.NET (las dos primeras se aplican prácticamente a todos los servidores web que permiten async IO) es que:

  1. ASP.NET utiliza un hilo diferente para cada solicitud entrante , por lo que obtiene una sobrecarga de cambio de contexto
  2. .NET no lo obliga a utilizar asincronización para realizar trabajos vinculados a IO, por lo que no es tan idiomático como nodejs donde las llamadas api vinculadas a IO son asincrónicas de facto (con devoluciones de llamadas)
  3. .NET ''"await-async" add es un paso en el tiempo de compilación para agregar "devoluciones de llamada", por lo que puede escribir código lineal (sin pasar la función de devolución de llamada), en contraste con nodejs

Hay tantos lugares en la web que describen la arquitectura del nodo, pero aquí hay algo: http://johanndutoit.net/presentations/2013/02/gdg-capetown-nodejs-workshop-23-feb-2013/index.html#1


La diferencia entre async en Nodejs y .NET está en el uso de multitarea preventiva para el código de usuario. .NET utiliza multitarea preventiva para el código de usuario, y Nodejs no.

Nodejs usa un grupo de subprocesos interno para atender solicitudes de E / S, y un solo subproceso para ejecutar su código de JS, incluidas las devoluciones de llamada de E / S.

Una de las consecuencias del uso de multitarea preventiva (.NET) es que un estado compartido puede ser alterado por otra pila de ejecución mientras se ejecuta una pila. Ese no es el caso en Nodejs: ninguna devolución de llamada desde una operación asíncrona puede ejecutarse simultáneamente con la pila que se está ejecutando actualmente. Otra acumulación de ejecución simplemente no existe en Javascript. El resultado de una operación asíncrona estará disponible para las devoluciones de llamada solo cuando la pila de ejecución actual finalice por completo. Tener eso, simple while(true); cuelga Nodejs, porque en este caso la pila actual no sale y el siguiente ciclo nunca se inicia.

Para entender la diferencia, considere los dos ejemplos, uno para js y uno para net. var p = new Promise (función (resolver) {setTimeout (resolver, 500, "mi contenido");}); p.then (función (valor) {// ... valor === "mi contenido"

En este código, puede colocar un controlador de forma segura (luego) después de "iniciar" una operación asincrónica, porque puede estar seguro de que ningún código de devolución de llamada que se inicie mediante una operación asíncrona se ejecutará hasta que salga la pila de llamadas actual. Las devoluciones de llamadas se manejan en los próximos ciclos. En cuanto a las devoluciones de llamada del temporizador, se tratan de la misma manera. Evento de temporizador asíncrono justs coloca el procesamiento de devolución de llamada en la cola para que se procese en un ciclo siguiente.

En .NET es diferente. No hay ciclos Hay multitarea preventiva.

ThreadPool.QueueUserWorkItem((o)=>{eventSource.Fire();}); eventSource.Fired += ()=>{ // the following line might never execute, because a parallel execution stack in a thread pool could have already been finished by the time the callback added. Console.WriteLine("1"); }

Aquí hay un código Hello World .NET a-la Nodejs para demostrar el procesamiento asincrónico en un solo subproceso y usar un grupo de subprocesos para async IO, al igual que el nodo. (.NET incluye versiones TPL e IAsyncResult de operaciones async IO, pero no hay diferencia para los propósitos de este ejemplo. De todos modos, todo termina con diferentes subprocesos en un grupo de subprocesos).

void Main() { // Initializing the test var filePath = Path.GetTempFileName(); var filePath2 = Path.GetTempFileName(); File.WriteAllText(filePath, "World"); File.WriteAllText(filePath2, "Antipodes"); // Simulate nodejs var loop = new Loop(); // Initial method code, similar to server.js in Nodejs. var fs = new FileSystem(); fs.ReadTextFile(loop, filePath, contents=>{ fs.WriteTextFile(loop, filePath, string.Format("Hello, {0}!", contents), ()=>fs.ReadTextFile(loop,filePath,Console.WriteLine)); }); fs.ReadTextFile(loop, filePath2, contents=>{ fs.WriteTextFile(loop, filePath2, string.Format("Hello, {0}!", contents), ()=>fs.ReadTextFile(loop,filePath2,Console.WriteLine)); }); // The first javascript-ish cycle have finished. // End of a-la nodejs code, but execution have just started. // First IO operations could have finished already, but not processed by callbacks yet // Process callbacks loop.Process(); // Cleanup test File.Delete(filePath); File.Delete(filePath2); } public class FileSystem { public void ReadTextFile(Loop loop, string fileName, Action<string> callback) { loop.RegisterOperation(); // simulate async operation with a blocking call on another thread for demo purposes only. ThreadPool.QueueUserWorkItem(o=>{ Thread.Sleep(new Random().Next(1,100)); // simulate long read time var contents = File.ReadAllText(fileName); loop.MakeCallback(()=>{callback(contents);}); }); } public void WriteTextFile(Loop loop, string fileName, string contents, Action callback) { loop.RegisterOperation(); // simulate async operation with a blocking call on another thread for demo purposes only. ThreadPool.QueueUserWorkItem(o=>{ Thread.Sleep(new Random().Next(1,100)); // simulate long write time File.WriteAllText(fileName, contents); loop.MakeCallback(()=>{callback();}); }); } } public class Loop { public void RegisterOperation() { Interlocked.Increment(ref Count); } public void MakeCallback(Action clientAction) { lock(sync) { ActionQueue.Enqueue(()=>{clientAction(); Interlocked.Decrement(ref Count);}); } } public void Process() { while(Count > 0) { Action action = null; lock(sync) { if(ActionQueue.Count > 0) { action = ActionQueue.Dequeue(); } } if( action!= null ) { action(); } else { Thread.Sleep(10); // simple way to relax a little bit. } } } private object sync = new object(); private Int32 Count; private Queue<Action> ActionQueue = new Queue<Action>(); }


La diferencia entre el modelo asíncrono de Node.js y el modelo async / await de C # es enorme. El modelo asíncrono que tiene Node.js es similar al antiguo modelo asincrónico en C # y .Net denominado Patrón asincrónico basado en eventos (EAP). C # y .Net tiene 3 modelos asíncronos, puede leer sobre ellos en Patrones de programación asíncrona . El modelo asincrónico más moderno en C # está basado en tareas con la asincrónica de C # y aguarda las palabras clave, puede leerlo en Patrón asincrónico basado en tareas . Las palabras clave async / await de C # hacen que el código asincrónico sea lineal y le permite evitar el "Infierno de devolución de llamada" mucho mejor que en cualquiera de los otros lenguajes de programación. Solo tienes que probarlo, y después de eso nunca lo harás de otra manera. Simplemente escriba operaciones asincrónicas que consuman código y no se preocupe por la legibilidad, ya que parece que escribe cualquier otro código. Por favor, mira estos videos:

  1. Programación asíncrona de inmersión profunda
  2. Async en ASP.NET
  3. Comprender asincrónica y Tareas pendientes

Y por favor, intente hacer algo asincrónico en C # y luego en Node.js para comparar. Verás la diferencia.

EDITAR : Como el motor JavaScript Node.js V8 admite generadores, definidos en ECMAScript 6 Draft , el "código de retorno de llamada" en JavaScript también se puede evitar fácilmente. Trae alguna forma de async / await a la vida en JavaScript