¿Cuál es la forma correcta de ejecutar una función de forma asíncrona en Electron?

Quiero ejecutar una función simple de forma asíncrona en Electron, para que no bloquee mi subproceso de procesamiento. Entonces, algo (muy aproximado) como este (dentro de render.js ):

 var max = 42; // Somehow needs to be passed to the function function foo() { for (var i = 0; i < max; i++) { // Do something... // ... and tell the render thread about it. } } foo(); // Should run asynchronously 

Hay dos requisitos:

  • Debo pasar parámetros a la función (aquí: max ). Estos no solo pueden ser enteros, sino también objetos. La función no debe ejecutarse antes de recibir estos parámetros.
  • Mientras se ejecuta, debe haber un canal de comunicación al subproceso de procesamiento. Por ejemplo, para informar periódicamente el progreso desde dentro del bucle for hasta la interfaz de usuario, o para abortar la función cuando se activa un evento en el subproceso de procesamiento.

Aquí hay un ejemplo de trabajo mínimo más específico (o más bien, no funciona) . El propósito es enviar comandos en serie a un aparato físico, en el cual se debe mover una sonda a todas las ubicaciones en una cuadrícula específica. Así que necesito dos bucles (uno para x, uno para y). El cuerpo del bucle contendrá funciones que se bloquean hasta que los motores se hayan movido, por lo que una medición de esa ubicación debe comunicarse a la interfaz de usuario. Además, antes de que los bucles comiencen a ejecutarse, se deben conocer las especificaciones sobre la cuadrícula (de ahí mi requisito sobre la transmisión de parámetros).

 var Parameters = {x_length: 50, y_length: 50}; //These functions interact with a serial device and block until it is done with its task function moveTo(x, y) {/*...*/}; function measure() {/*...*/}; //This function should eventually be executed asynchronously function scan() { for (var x = 0; x < Parameters.x_length; x++) { for (var y = 0; y < Parameters.y_length; y++) { moveTo(x, y); var result = measure(); // Here, we need to tell the render thread about results. I used // postMessage (WebWorker syntax) as a placeholder. postMessage({ position: {x: x, y: y}, data: result }); } } } // This is what will be actually called, eg when the user clicks a // button. function scan_async() { //Again, I used WebWorker (or rather, TinyWorker) syntax as a placeholder. var scan_worker = new Worker(scan); scan_worker.onmessage = function (msg) { console.log(msg.data); }; } 

Después de horas de googeling muy frustrante, encontré muchos enfoques, pero ninguno de ellos parece ser la forma “definitiva” de hacerlo, o no cumple con los puntos anteriores, o parece ser una forma complicada de lograr lo que quiero lograr.

Lo que encontré hasta ahora:

  • En realidad, utilizando WebWorkers (o más bien algo TinyWorkers, https://github.com/avoidwork/tiny-worker ), como en el código anterior. Aquí, parece que no hay una forma elegante de pasar los parámetros de inicio antes de que el trabajador comience a correr.
  • Crea una nueva BrowserWindow oculta, como se menciona aquí . Sin embargo, no puedo encontrar nada acerca de este método en otro lugar.

Entonces, ¿hay una forma “correcta” y más directa de lograr mi objective?

En realidad utilizando WebWorkers (o más bien algo TinyWorkers)

Sí. Así es como mueves el código a un hilo diferente.

Aquí, parece que no hay una forma elegante de pasar los parámetros de inicio antes de que el trabajador comience a correr.

  1. Crea al trabajador. No haga que haga nada, excepto escuchar los eventos postMessage .
  2. Envíale un mensaje, con postMessage con los parámetros iniciales
  3. Un detector de eventos en el trabajador recibe el mensaje y comienza a ejecutar el trabajo.
  4. Cuando haya terminado, postMessage el postMessage del trabajo a la aplicación principal.
  5. Un detector de eventos en la aplicación principal recibe el mensaje con los resultados