【问题标题】:Javascript Web Worker - How to ignore all messages except the last one?Javascript Web Worker - 如何忽略除最后一条以外的所有消息?
【发布时间】:2015-07-11 17:21:09
【问题描述】:

我有一系列 UI 滑块 (dat.GUI),每当 UI 滑块发生变化时,我都会将滑块值发布给 Web Worker。
在工作人员中完成的计算大约需要 3-8 秒,直到工作人员发回我需要的信息。

如果 UI 界面被快速使用(例如,在第一次计算完成之前更改了 5 个滑块),worker 仍然收到了 5 条消息,并且仍然会响应每条消息,每条新信息都会覆盖最后一个。工人有什么办法可以忽略中间消息,只在当前计算完成之前使用最后收到的消息执行计算?

我是工人的初学者,所以现在我只使用 Worker.onmessage 属性和 Worker.postMessage() 方法。

【问题讨论】:

  • 告诉我们更多关于您的架构的信息。现在工人怎么会是最后一条消息?如果是提前知道的,那为什么其他消息一开始就发给worker呢?
  • 使用debounce怎么样?它会稍微延迟处理,如果在此延迟期间收到一条新消息,它会丢弃第一个消息并将新消息延迟一点,重复此操作直到消息停止发送。
  • @doldt 发送所有消息是因为每次一个滑块值发生更改时都应执行新计算,但同​​时用户可以随时继续使用或停止使用滑块,所以我这样做不知道哪个是最后一条只发送的消息。我想“工人怎么知道最后一条消息”是我自己问题的一部分。
  • @DCoder 我会检查 debounce 是什么,看看它是否有帮助,即使我更愿意避免延迟处理,我正在寻找如何完全跳过处理轮次,以防多条消息有被堆叠了。
  • @des 我看到您想在收到新消息后终止先前处理的任务。请记住,这种方法存在一些挑战。工作人员本身是严格的单线程。这就是 JavaScript 避免同步问题的方式。因此,假设您的工作人员收到一条消息,然后开始了一个需要 5 秒的超级密集程序。然后用户在 1 秒后进行另一个 UI 交互,因此向同一个工作人员发送了一条新消息。工作线程的onmessage 回调要等到 4 秒后线程释放时才会启动。

标签: javascript web-worker postmessage


【解决方案1】:

这与 WebWorker 没有太大关系。这似乎是一个典型的去抖动用例。这里的问题是,一旦您的工作人员收到一条消息,它怎么知道它是最后一条?它不能告诉未来。它不知道用户是否会在不久的将来进行另一个 UI 交互。所以解决这类问题的方法就是去抖。这个想法是您不会立即执行您的代码,而是稍等一下,比如 200 毫秒。在这段时间内,如果有另一个消息,那么它会再等待 200 毫秒而不做任何事情。你可以自己实现这样的东西,或者你可以导入和使用现有的库之一,比如underscore.js

编辑:这是一个使用 underscore.js/lodash 的示例(两者都有类似的 API)。 假设最初,您的代码是这样的:

onmessage = function(e) {
    var params = e.data.something;
    // TODO: Do something with params.
};

使用 debounce,您将把它重写为...

onmessage = _.debounce(function(e){
    var params = e.data.something;
    // TODO: Do something with params.
}, 200);

这里发生的是_.debounce 返回一个包装函数,可以根据需要随时调用该函数。但是它不会立即触发包裹在里面的函数。它安排它在 200 毫秒内执行(根据您的需要进行调整)。在此期间,如果再次调用,则会取消之前预定的执行,此时会在 200ms 内安排新的执行。时间到了,您的函数将使用最新版本的参数执行。现在您可能想知道以前调用的参数会发生什么?答案是它们被包装函数简单地丢弃了。请注意,传递给onmessage 的参数首先传递给包装函数,它只保留要传递给包装函数的最新参数。您可以使用我在此处创建的fiddle 来查看它的实际效果。我想补充的另一个注意事项是,您也可以在主线程上执行此去抖动逻辑,然后再将其传递给 WebWorker。

编辑:如果您需要有关如何在 WebWorker 中导入第三方库的指南。 https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers#Importing_scripts_and_libraries

【讨论】:

  • 我决定使用去抖动。我知道如何在 WebWorker 中导入库,但我仍然对如何实现该功能感到困惑。现在,在我的工作人员中,我有: onmessage = function(e) { //(1 - 获取从主线程发送的值) sliderValues = e.data.sliderValues; //(2 - 执行计算) getMeshInformation(); //(3 - 发布结果) postMessage({ 'triangles' : triangles }); };现在我只想执行 1 号,然后等待(去抖动)2 号 3 号,以防它收到一个新的 1 号,它会覆盖前一个。
  • 如果您使用现有的实现之一,您真正需要做的就是用 debounce 包装您的原始 onmessage 回调,仅此而已。但是,如果您想自己实现,可以查看underscore.jslodash 的源代码以获得一些灵感。当然,您的实现不需要那么花哨。我将在上面编辑我的答案以包含一个示例,因为在评论中发布代码很难看。
  • 感谢您的宝贵时间,这很有帮助。
猜你喜欢
  • 2011-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-21
  • 1970-01-01
  • 2014-05-23
  • 1970-01-01
相关资源
最近更新 更多