What's the correct way to run a function asynchronously in Electron?

早过忘川 提交于 2019-12-11 18:56:34

问题


I want to run a simple function asynchronously in Electron, so it doesn't block my render thread. So, something (very roughly) like this (within 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

There are two requirements:

  • I must pass parameters to the function (here: max). These could not only be integers, but also objects. The function must not run before it recieves these parameters.
  • While running, there must be a communication channel to the render thread. For example, to periodically report progress from within the for loop all the way to the UI, or to abort the function when an event in the render thread fires.

Here is a more specific minimal working (or rather, not working) example. The purpose is to send serial commands to a physical apparatus, on which a probe should be moved to all locations in a specified grid. So I need two loops (one for x, one for y). The loop body will contain functions that block until the motors have moved, than a mesurement from that location must be communicated back to the UI. Also, before the loops start running, the specifications about the grid must be known (hence my requirement about passing parameters.)

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, e. g.  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);
    };
}

After hours of very frustrating googeling, I found a lot of approaches, but non of them seems like the "definitive" way to do it, or doesn't meet the above points, or seems way to complicated for what I want to achieve.

What I found so far:

  • Actually using WebWorkers (or rather something TinyWorkers, https://github.com/avoidwork/tiny-worker), like in the code above. Here, there seems to be no elegant way to pass the starting parameters before the worker starts running.
  • Create a new, hidden BrowserWindow, as mentioned here. However, I can't find anything about this method elsewhere.

So, is there a "correct", more straight-forward way to achieve my goal?


回答1:


Actually using WebWorkers (or rather something TinyWorkers)

Yes. This is how you move code to a different thread.

Here, there seems to be no elegant way to pass the starting parameters before the worker starts running.

  1. Create the worker. Don't have it do anything except listen for postMessage events.
  2. Send a message to it, with postMessage with the starting parameters
  3. An event listener in the worker gets the message and starts running the job
  4. When it is done, postMessage from the work to the main application
  5. An event listener in the main application gets the message with the results


来源:https://stackoverflow.com/questions/51795352/whats-the-correct-way-to-run-a-function-asynchronously-in-electron

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!