如何确保 Web Worker 只处理最后一条消息?

问题描述 投票:0回答:1

我有一个场景,用户可能会快速产生事件(例如悬停)。每次悬停都会向网络工作人员发送一条消息以进行一些计算。 每条新消息都应取消前一条消息,并且我需要确保仅处理最后一条消息并将其结果返回到 UI 线程。

如何确保 Web Worker 仅处理它收到的最后一条消息? 我想避免任何去抖时间,因为延迟最小化很重要。

javascript angular web-worker
1个回答
0
投票

我创建了 NPM 包 @wjfe/async-workers,它提供了一个名为

CancellationSource
的类。 此类使用
SharedArrayBuffer
将取消任务的愿望传输给 Web Worker,无需函数生成器或异步编程。 您只需在 FOR 循环中使用
CancellationSource.throwIfSignaled()
即可取消。

这个类可以单独使用,但我建议您使用

AsyncWorker
类,因为它简化了传递缓冲区的麻烦,并且还为整个 Web Worker 使用提供了一个很好的异步语法。

一个例子:

// myWorker.ts
import { CancellationSource, workerListener, type PostFn, type Token } from "@wjfe/async-workers";

export const myWorker = {
  calculate(payload: Payload, _: PostFn, cancelToken: Token): MyData {
    for (let i = 0; i < someCap; ++i) {
      CancellationSource.throwIfSignaled();
      // Calculate
    }
    return result;
};

export type MyWorker = typeof myWorker;

self.onMessage = workerListener(myWorker);

然后在UI线程中:

// user-file.ts
import { myWorker } from "myWorker.js";

const worker = getWorkerSomehowDependingOnYourToolingSuchAsVite();

const controller = new AsyncWorker(worker, myWorker);

现在您可以使用

controller
来启动工作:

// somewhere.ts
let workItem: WorkItem | undefined;

myElement.addEventListener('hover', () => {
  workItem?.cancel();
  workItem = controller.enqueue.calculate(undefined, { cancellable: true });
});

或者类似的东西。 请遵循存储库的自述文件以获得更高的准确性。

您在上面看到的是一个事件侦听器,它将首先取消之前的工作项,然后在每次事件触发时生成一个新的工作项。

重要:为此,您必须满足跨域隔离的条件。

© www.soinside.com 2019 - 2024. All rights reserved.