使用 React 获取 Web Worker
Fetch in a Web Worker using React
我有一个 React 页面,要求用户输入一些信息,returns 是一个 API 对象的数组 JSON。
查询可能 return 导致页面在加载 fetch 时冻结的大结果,所以我想使用 web worker 来分离线程并添加加载轮让用户知道网站没有崩溃。
我目前的网络工作者使用此代码:
工人代码
const self = this;
export default () => {
self.addEventListener('message', e => {
if (!e) return;
let query = e.data;
let res = null;
fetch(`https://statsapi.web.nhl.com/api/v1/schedule?startDate=${query}&endDate=${query}`)
.then(response => {
return response.json();
})
.then(function(_ref) {
postMessage(_ref);
});
});
};
这只是一个例子 API,但真正的 API 结果会更大,加载时间也更长。
我也使用function(_ref)
而不是({ data }) =>
,因为当通过babel处理时,({ data }) =>
会在没有通过ref的数据访问器时变成_ref.data
, _ref
在 return 数组中工作。
我在 Web Worker class 中实现了我的代码,如下所示:
工人构造函数
export default class WebWorker {
constructor(worker) {
const code = worker.toString();
const blob = new Blob(['(' + code + ')()'], { type: 'text/javascript' });
return new Worker(URL.createObjectURL(blob));
}
}
我在另一个class中这样称呼webworker:
Web Worker 创建
componentDidMount = () => {
this.worker = new WebWorker(worker);
}
getInfo = () => {
this.worker.postMessage(this.state.query);
this.setState(prevState => ({
...prevState,
open: true
}), () => {
this.worker.addEventListener('message', (event) => {
const res = event.data;
this.setState({
results: res,
open: false
});
});
});
}
我一直 运行 遇到的问题是,当我尝试像现在这样调用它时,网络工作者似乎没有在另一个线程上处理。即使 web worker 正在获取数据,页面仍然冻结,因为它在冻结后仍正确设置状态。
我是 web worker 的新手,所以我是否遗漏了一些可以让它工作的东西,或者是否有一种不同的方式来使用带有 fetch 的 web worker?
您首先需要确定是什么问题。来自 API 的响应可能很好,但是如果您对数以万计的对象执行 "stuff" - 循环、排序、映射等 -(或呈现数千个元素),那么您的页面性能很可能会遭受重大损失。
像分页这样简单的东西可能就是所有问题的答案。
如果您的页面变得无响应,则表明主处理线程正受到 CPU 绑定操作的影响。 I/O-bound 操作,例如从 URL 中获取,不会影响您页面的响应能力,除了响应的一些解析开销。因此,worker 的最佳用法是在不同的线程上执行 CPU 密集型操作。将 I/O 操作转移给工作人员,您在性能方面获得的收益很少(如果有的话)。
很可能是您的渲染逻辑或数据处理导致了挂起,而不是网络请求处理。
我有一个 React 页面,要求用户输入一些信息,returns 是一个 API 对象的数组 JSON。
查询可能 return 导致页面在加载 fetch 时冻结的大结果,所以我想使用 web worker 来分离线程并添加加载轮让用户知道网站没有崩溃。
我目前的网络工作者使用此代码:
工人代码
const self = this;
export default () => {
self.addEventListener('message', e => {
if (!e) return;
let query = e.data;
let res = null;
fetch(`https://statsapi.web.nhl.com/api/v1/schedule?startDate=${query}&endDate=${query}`)
.then(response => {
return response.json();
})
.then(function(_ref) {
postMessage(_ref);
});
});
};
这只是一个例子 API,但真正的 API 结果会更大,加载时间也更长。
我也使用function(_ref)
而不是({ data }) =>
,因为当通过babel处理时,({ data }) =>
会在没有通过ref的数据访问器时变成_ref.data
, _ref
在 return 数组中工作。
我在 Web Worker class 中实现了我的代码,如下所示:
工人构造函数
export default class WebWorker {
constructor(worker) {
const code = worker.toString();
const blob = new Blob(['(' + code + ')()'], { type: 'text/javascript' });
return new Worker(URL.createObjectURL(blob));
}
}
我在另一个class中这样称呼webworker:
Web Worker 创建
componentDidMount = () => {
this.worker = new WebWorker(worker);
}
getInfo = () => {
this.worker.postMessage(this.state.query);
this.setState(prevState => ({
...prevState,
open: true
}), () => {
this.worker.addEventListener('message', (event) => {
const res = event.data;
this.setState({
results: res,
open: false
});
});
});
}
我一直 运行 遇到的问题是,当我尝试像现在这样调用它时,网络工作者似乎没有在另一个线程上处理。即使 web worker 正在获取数据,页面仍然冻结,因为它在冻结后仍正确设置状态。
我是 web worker 的新手,所以我是否遗漏了一些可以让它工作的东西,或者是否有一种不同的方式来使用带有 fetch 的 web worker?
您首先需要确定是什么问题。来自 API 的响应可能很好,但是如果您对数以万计的对象执行 "stuff" - 循环、排序、映射等 -(或呈现数千个元素),那么您的页面性能很可能会遭受重大损失。
像分页这样简单的东西可能就是所有问题的答案。
如果您的页面变得无响应,则表明主处理线程正受到 CPU 绑定操作的影响。 I/O-bound 操作,例如从 URL 中获取,不会影响您页面的响应能力,除了响应的一些解析开销。因此,worker 的最佳用法是在不同的线程上执行 CPU 密集型操作。将 I/O 操作转移给工作人员,您在性能方面获得的收益很少(如果有的话)。
很可能是您的渲染逻辑或数据处理导致了挂起,而不是网络请求处理。