tl;dr 资源预加载为
<link rel="preload" href="..." as="fetch" crossorigin="anonymous">
似乎没有被 Web Worker 中发生的
fetch
调用使用。
这是为什么?是否需要对预加载标签进行更改或其他解决方法?
上下文: 我有一个 Web Worker,它下载并处理大量的 CSV 数据。处理非常密集,所以我想把它放在主线程之外。
但是,我喜欢一种更早启动下载的方法,以便工作人员可以在工作人员启动后尽快开始处理它。
我尝试为资源添加一个
<link rel="preload" as="fetch" ...>
,这对于从 main 线程获取数据非常有用——但是如果我从 worker 获取相同的资源,预加载的资源是 not 使用(一个单独的请求已启动,我可以看到标准的“资源已使用链接预加载进行预加载,但在窗口加载事件后几秒钟内未使用”警告打印到控制台。
事实上,即使工人确实拥有相同的(克隆)Policy Container作为他们的所有者
Document
,仅此而已,并且预加载资源的map不共享。
所以对于你的情况,你可以做的是使用你的
<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
就可以进入缓存了。