预加载"获取"资源以供web工作程序使用



tl;dr资源预加载为

<link rel="preload" href="..." as="fetch" crossorigin="anonymous">

似乎不会被Web Worker中发生的fetch调用使用。

为什么会这样?我是否需要对预加载标签进行更改,或者采取其他解决方法?


上下文:我有一个Web Worker,它下载并处理大量CSV数据。处理相当密集,所以我想把它放在主线程之外。

然而,我希望有一种方法可以更早地启动下载,这样工作人员就可以在工作人员启动后更快地开始处理它。

我尝试为资源添加一个<link rel="preload" as="fetch" ...>,这对于从main线程获取非常有效——但如果我从工作线程获取相同的资源,如果预加载的资源未使用(启动了一个单独的请求,我可以看到控制台上打印的标准"资源已使用链接预加载进行预加载,但在窗口加载事件后的几秒钟内未使用"警告)。

事实上,尽管Workers确实拥有与其所有者Document相同的(克隆)策略容器,但仅此而已,并且预加载资源的映射是不共享的。

因此,对于您的情况,您可以使用<link>fetch()在主线程中预加载,将Response作为ArrayBuffer(这是最原始的格式)使用,并将ArrayBuffer传输到Worker:

<link rel="preload" href="..." as="fetch" crossorigin="anonymous">
// ...
const resp = await fetch("...");
if (!resp.ok) { handleNetworkError(resp) }
const buffer  = await resp.arrayBuffer();
const worker = new Worker(/*...*/);
worker.postMessage({ buffer }, [buffer]);

在你的Worker中,你会做

onmessage = ({ data }) => {
if (data.buffer) {
const csvText = new TextDecoder().decode(data.buffer);
parseCSV(csvText);
}
};

这样做,您仍然可以利用预加载,并且对主线程的影响仍然非常小:获取是并行进行的,将Response作为ArrayBuffer消耗掉不需要任何计算,也不应该将数据传输到Worker。但这比直接从Worker中获取要复杂一些。

根据您的情况,另一个解决方案可能是使用ServiceWorker预取资源并缓存它们。然后,您的Worker就可以点击缓存了。

相关内容

  • 没有找到相关文章

最新更新