ejecutar - llamar funcion javascript html sin evento
¿Cómo ocurre la ejecución asincrónica de Javascript? y cuando no usar declaración de devolución? (2)
En primer lugar, pasar una función como parámetro le dice a la función que está llamando que le gustaría llamar a esta función en el futuro. Cuando exactamente en el futuro se llamará depende de la naturaleza de lo que está haciendo la función.
Si la función está haciendo alguna conexión de red y la función está configurada para ser no bloqueante o asíncrona, la función se ejecutará, la operación de red se iniciará y la función que usted llamó volverá de inmediato y el resto de su código javascript en línea después esa función se ejecutará. Si devuelve un valor de esa función, volverá inmediatamente, mucho antes de que se haya llamado a la función que pasó como parámetro (la operación de red aún no se ha completado).
Mientras tanto, la operación de red va en segundo plano. Está enviando la solicitud, escuchando la respuesta y luego reuniendo la respuesta. Cuando la solicitud de red se haya completado y la respuesta se haya recopilado, ENTONCES y solo entonces la función original a la que llamó llamará a la función que aprobó como parámetro. Esto puede ser solo unos pocos milisegundos más tarde o puede durar unos minutos más tarde, dependiendo de cuánto tiempo tardó en completarse la operación de red.
Lo que es importante entender es que en su ejemplo, la llamada a la función db.get()
ha completado hace mucho tiempo y el código se ha ejecutado secuencialmente después de que también se haya ejecutado. Lo que no se ha completado es la función anónima interna que pasó como parámetro para esa función. Eso se mantiene en un cierre de función javascript hasta más tarde cuando finaliza la función de red.
En mi opinión, una cosa que confunde a mucha gente es que la función anónima se declara dentro de tu llamada a db.get y parece ser parte de eso y parece que cuando se hace db.get()
, esto se haría también, pero ese no es el caso. Quizás eso sería menos parecido si se representara de esta manera:
function getCompletionfunction(result) {
// do something with the result of db.get
}
// asynchronous Javascript
db.get(''select * from table1'', getCompletionFunction);
Entonces, tal vez sería más obvio que db.get regresará inmediatamente y getCompletionFunction se llamará en algún momento en el futuro. No estoy sugiriendo que lo escriba de esta manera, sino simplemente mostrando esta forma como un medio para ilustrar lo que realmente está sucediendo.
Aquí hay una secuencia que vale la pena entender:
console.log("a");
db.get(''select * from table1'', function(result){
console.log("b");
});
console.log("c");
Lo que verías en la consola del depurador es esto:
a
c
b
"a" pasa primero. Luego, db.get () inicia su operación y luego regresa inmediatamente. Por lo tanto, "c" sucede a continuación. Entonces, cuando la operación db.get () realmente completa algún tiempo en el futuro, ocurre "b".
Para leer sobre cómo funciona el manejo de sincronización en un navegador, consulte ¿Cómo maneja JavaScript las respuestas AJAX en el fondo?
// synchronous Javascript
var result = db.get(''select * from table1'');
console.log(''I am syncronous'');
// asynchronous Javascript
db.get(''select * from table1'', function(result){
// do something with the result
});
console.log(''I am asynchronous'')
Sé que en el código síncrono, console.log () se ejecuta después de obtener el resultado de db, mientras que en el código asincrónico console.log () se ejecuta antes de que db.get () obtenga el resultado.
Ahora mi pregunta es, ¿cómo ocurre la ejecución entre bastidores para el código asíncrono y por qué no es bloqueante?
He buscado el estándar Ecmascript 5 para entender cómo funciona el código asíncrono, pero no pude encontrar la palabra asíncrona en todo el estándar.
Y desde nodebeginner.org también descubrí que no deberíamos usar una instrucción return ya que bloquea el ciclo de eventos. Pero nodejs api y los módulos de terceros contienen declaraciones de retorno en todas partes. Entonces, ¿cuándo se debe usar una declaración de devolución y cuándo no?
¿Alguien puede arrojar algo de luz sobre esto?
share explica la asincronía, ya que se aplica bastante bien a la mayoría de los usuarios, pero en tu comentario share querer más detalles sobre la implementación:
[...] ¿Puede algún organismo escribir algún pseudo código, explicando la implementación de la especificación Ecmascript para lograr este tipo de funcionalidad? para una mejor comprensión de las partes internas de JS.
Como probablemente sepa, una función puede guardar su argumento en una variable global. Digamos que tenemos una lista de números y una función para agregar un número:
var numbers = [];
function addNumber(number) {
numbers.push(number);
}
Si agrego algunos números, siempre que me refiera a la misma variable de numbers
que antes, puedo acceder a los números que agregué anteriormente.
Es probable que las implementaciones de JavaScript hagan algo similar, excepto que en lugar de guardar números, guardan las funciones (específicamente, las funciones de devolución de llamada).
The Event Loop
En el núcleo de muchas aplicaciones se encuentra lo que se conoce como un ciclo de eventos. En esencia, se ve así:
- bucle para siempre:
- obtener eventos, bloqueando si no existe
- procesar eventos
Supongamos que desea ejecutar una consulta de base de datos como en su pregunta:
db.get("select * from table", /* ... */);
Para realizar esa consulta de base de datos, es probable que necesite realizar una operación de red. Dado que las operaciones de red pueden llevar un tiempo considerable, durante el cual el procesador está esperando, tiene sentido pensar que tal vez deberíamos, en lugar de esperar en lugar de hacer otro trabajo, hacer que nos diga cuándo está listo para que podamos hacer otras cosas mientras tanto.
En aras de la simplicidad, pretenderé que el envío nunca bloqueará / bloqueará sincrónicamente.
La funcionalidad de get
podría verse así:
- generar identificador único para solicitud
- enviar fuera de petición (de nuevo, por simplicidad, suponiendo que esto no bloquea)
- guardar par (identificador, devolución de llamada) en un diccionario global / tabla hash variable
Eso es todo lo que harías; no hace ninguno de los bits de recepción, y no es responsable de llamar a su devolución de llamada. Eso sucede en el bit de eventos de proceso. El bit de eventos de proceso podría verse (parcialmente) así:
- ¿Es el evento una respuesta de la base de datos? si es así:
- analizar la respuesta de la base de datos
- buscar el identificador en la respuesta en la tabla hash para recuperar la devolución de llamada
- llamar a la devolución de llamada con la respuesta recibida
Vida real
En la vida real, es un poco más complejo, pero el concepto general no es muy diferente. Si desea enviar datos, por ejemplo, es posible que tenga que esperar hasta que haya espacio suficiente en los búferes de red salientes del sistema operativo antes de poder agregar su bit de datos. Al leer datos, puede obtenerlos en varios fragmentos. El bit de eventos de proceso probablemente no sea una función grande, sino que solo llama a un montón de devoluciones de llamadas (que luego envían a más devoluciones de llamada, y así sucesivamente ...)
Si bien los detalles de implementación entre la vida real y nuestro ejemplo son ligeramente diferentes, el concepto es el mismo: se inicia "haciendo algo" y se llamará a una devolución de llamada a través de algún mecanismo u otro cuando se termine el trabajo.