【问题标题】:What's the correct way to run a function asynchronously in Electron?在 Electron 中异步运行函数的正确方法是什么?
【发布时间】:2018-08-11 18:39:59
【问题描述】:

我想在 Electron 中异步运行一个简单的函数,所以它不会阻塞我的渲染线程。所以,像这样的东西(非常粗略)(在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

有两个要求:

  • 我必须将参数传递给函数(这里:max)。这些不仅可以是整数,还可以是对象。该函数在收到这些参数之前不得运行。
  • 在运行时,必须有一个到渲染线程的通信通道。例如,定期报告从 for 循环一直到 UI 的进度,或者在渲染线程中的事件触发时中止函数。

这是一个更具体的最小工作(或者更确切地说,不工作)示例。目的是将串行命令发送到物理设备,在该物理设备上,探针应移动到指定网格中的所有位置。所以我需要两个循环(一个用于 x,一个用于 y)。循环体将包含在电机移动之前阻塞的功能,然后必须将来自该位置的测量值传达回 UI。此外,在循环开始运行之前,必须知道有关网格的规范(因此我要求传递参数。)

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);
    };
}

经过数小时非常令人沮丧的谷歌搜索后,我找到了很多方法,但没有一种方法似乎是“确定”的方法,或者不符合上述几点,或者对于我想要的东西来说似乎很复杂去实现。

到目前为止我发现了什么:

  • 实际上使用 WebWorkers(或者更确切地说是 TinyWorkers,https://github.com/avoidwork/tiny-worker),就像上面的代码一样。在这里,似乎没有优雅的方法可以在 worker 开始运行之前传递启动参数。
  • 创建一个新的隐藏BrowserWindow,如here 所述。但是,我在其他地方找不到有关此方法的任何信息。

那么,有没有一种“正确”、更直接的方式来实现我的目标?

【问题讨论】:

  • 不知何故使用节点的异步 - 这不是节点的异步。这是每个人的异步,它是 ES2017。问题不够具体。请解释您的实际问题,而不仅仅是 foo 抽象。解决方案取决于它。 做某事 - 这是什么?真的只有 42 次迭代吗? 在运行时,必须有一个到渲染线程的通信通道 - 这没有显示。请向stackoverflow.com/help/mcve 提供您当前的尝试,清楚地表明您真正想要做什么。
  • 对不起,如果我太含糊了。我希望现在好多了:)
  • 将长时间运行的代码放入 Promise 中不会将该代码推送到不同的线程。 async 帮不了你。
  • 好的,我将删除那个项目符号。
  • @jmb @ 必须用于参与者接收通知。是的,这更好,但重要的细节尚不清楚。测量是如何工作的,为什么它会阻塞?这很重要。它使用的功能可能在 web worker 中不可用。通常,您在浏览器中为网络工作者提供 CPU 密集型或阻塞代码 - 或者如果它是 Node.js 则将其分叉。您仍然可以在需要时使用 async/await。

标签: javascript node.js electron


【解决方案1】:

实际上使用 WebWorkers(或者更确切地说是 TinyWorkers)

是的。这就是您将代码移动到不同线程的方式。

这里,似乎没有优雅的方式在worker开始运行之前传递启动参数。

  1. 创建工作器。除了侦听postMessage 事件之外,不要让它做任何事情。
  2. 向它发送一条消息,带有postMessage 和起始参数
  3. worker 中的事件侦听器获取消息并开始运行作业
  4. 完成后,postMessage 从工作到主应用程序
  5. 主应用程序中的事件侦听器获取带有结果的消息

【讨论】:

  • 啊,所以基本上,把整个工作代码放在self.onmessage 事件中?这就是我所说的“看起来不优雅”的意思,例如。 G。因为它阻止了向工作人员发送进一步消息的可能性,如果我将来需要的话。还是我理解错了?
  • 我看不出它会如何阻止向工作人员发送更多消息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多