javascript node.js promise

javascript - Forma correcta de escribir la función de no fumar en node.js



promise (1)

Envolver el código en una promesa (como lo has hecho) no lo hace sin bloqueo. La función Ejecutor de Promesas (la devolución de llamada que se pasa a la new Promise(fn) se llama de forma síncrona y se bloqueará, por lo que se ve la demora en obtener la salida.

De hecho, no hay forma de crear su propio código de Javascript simple (como lo que tiene) que no sea de bloqueo, excepto ponerlo en un proceso secundario, usando una biblioteca de terceros que cree nuevos hilos de Javascript o usando el nuevo nodo experimental .js APIs para hilos. Regular node.js ejecuta su Javascript como bloqueo y subproceso único, ya sea envuelto en una promesa o no.

Puede usar elementos como setTimeout() para cambiar "cuándo" se ejecuta su código, pero siempre que se ejecute, seguirá bloqueando (una vez que comience a ejecutarse, nada más puede ejecutarse hasta que se haga). Todas las operaciones asíncronas en la biblioteca node.js utilizan alguna forma de código nativo subyacente que les permite ser asíncronas (o simplemente usan otras API asincrónicas de node.js que ellos mismos usan implementaciones de código nativo).

Pero el programa espera antes de imprimir segunda y tercera líneas. ¿Puede explicar cuál debería ser la forma correcta de imprimir "antes" y "después" primero y luego (después de un tiempo) el resultado?

Como dije anteriormente, envolver las cosas en la función ejecutora de promesa no las hace asíncronas. Si desea "cambiar" el tiempo en que se ejecutan las cosas (aunque aún son sincrónicas), puede usar un setTimeout() , pero eso no hace que nada se bloquee, simplemente lo hace funcionar más tarde (aún bloqueando cuando carreras).

Entonces, podrías hacer esto:

function longRunningFunc(val, mod) { return new Promise((resolve, reject) => { setTimeout(() => { sum = 0; for (var i = 0; i < 100000; i++) { for (var j = 0; j < val; j++) { sum += i + j % mod } } resolve(sum) }, 10); }) }

Eso volvería a programar el tiempo que demoraría la ejecución for bucle más tarde y podría "parecer" que no está bloqueando, pero en realidad aún se bloquea, simplemente se ejecuta más tarde. Para que sea realmente no bloqueante, tendrías que usar una de las técnicas mencionadas anteriormente para sacarlo del hilo principal de Javascript.

Formas de crear un código real de no bloqueo en node.js:

  1. Ejecútelo en un proceso secundario separado y reciba una notificación asíncrona cuando se haga.
  2. Utilice los nuevos subprocesos de trabajo experimentales en node.js v11
  3. Escriba su propio complemento de código nativo en node.js y use subprocesos libuv o subprocesos de nivel de SO en su implementación (u otras herramientas asíncronas de nivel de SO).
  4. Cree sobre las API asíncronas existentes anteriormente y no tenga ninguno de su propio código que demore mucho en el hilo principal.

Escribí una función simple que devuelve Promise por lo que debería ser sin bloqueo (en mi opinión). Desafortunadamente, el programa parece que deja de esperar a que la Promesa termine. No estoy seguro de lo que puede estar mal aquí.

function longRunningFunc(val, mod) { return new Promise((resolve, reject) => { sum = 0; for (var i = 0; i < 100000; i++) { for (var j = 0; j < val; j++) { sum += i + j % mod } } resolve(sum) }) } console.log("before") longRunningFunc(1000, 3).then((res) => { console.log("Result: " + res) }) console.log("after")

La salida parece esperada:

before // delay before printing below lines after Result: 5000049900000

Pero el programa espera antes de imprimir segunda y tercera líneas. ¿Puede explicar cuál debería ser la forma correcta de imprimir "antes" y "después" primero y luego (después de un tiempo) el resultado?