15

我想知道你对此有何看法。是否建议在 web worker 中使用同步请求(XMLHttpRequest)?我能找到什么问题?

我一直在我的应用程序中对此进行测试,但没有发现任何问题。但由于 jQuery 和 AJAX 的旧经验,我害怕这种同步行为。我的应用程序从数据库中的多个表中获取大量数据,这需要时间。对于从表中检索到的每一束数据,我需要立即处理它,以免过多地延迟整个事情。同时,用户正在与浏览器交互,所以它可以被阻止,我认为网络工作者可以正常工作。你认为这是一个好的解决方案吗?或者我应该尝试异步请求?

谢谢你。

4

2 回答 2

20

我没有确凿的事实,但既然你征求意见...... :)

Chrome 中有一个明显的问题:太多的 Web Worker 会导致静默崩溃(根据这个错误报告,上限约为 60-100 )。一般的问题是 Web Workers 是资源密集型的,至少在 v8 中是这样。

假设您最终要进行多个 HTTP 调用,如果您在 Web Worker 中进行同步 HTTP 调用:

  • 从某种意义上说,您正在为异步 Web Worker 交易异步 HTTP 调用,这只会在混合中添加另一个中介,您仍然必须异步管理事物。
  • 如果您采用更简单且资源效率更高的路线并且只使用一个 Web Worker,您将花费大量时间等待它给您响应。
  • 另一方面,如果您使用多个 Web Worker,您可能需要跟踪哪个是空闲的,哪个是忙碌的,等等,在这种情况下,您将创建一个自制的调度程序,而不是使用现有的调度程序。烘焙到浏览器中。
  • 最后,Web Worker 很昂贵(显然),您最终可能会创建多个 Web Worker,这样他们就可以坐下来等待 HTTP 调用完成。

我不认为自己是这方面的专家,所以请把它当作它的价值。

更新:为各种场景添加一些优点/缺点。

在使用 Web Worker 进行同步和异步 HTTP 调用之间进行选择时,会想到一些优点/缺点:

  • 通常,同步请求会更容易编写,并且会产生易于遵循的代码。同步请求的一个缺点是它们可能鼓励编写长函数,这些函数应该被分割成单独的、更小的函数。
  • 如果您进行单次调用,则两种方法完成所需的时间没有区别,同步更好,因为它更简单一些。我说它只是简单一点,因为带有一个回调侦听器的单个异步调用确实相当简单。
  • 如果您要进行多个必须以特定顺序发生的调用,例如加载用户的个人资料数据,然后根据他们的地址获取当地天气,那么同步调用会更好,因为它更容易编写并且更容易读。阅读它的主要内容是调用中的顺序依赖关系将通过选择同步进行调用及其在函数中的顺序来清楚地概述。呼叫越多,这就越重要。如果有很多调用,复杂性上的差异可能会很大。
  • 如果您必须进行不需要以任何特定顺序发生的多次调用,那么异步请求会更好,因为整个过程可能比同步请求快几个数量级。您拨打的电话越多或连接速度越慢,总经过时间的差异就越大;这种差异会迅速增长(呈指数增长?)。从阅读代码的人的角度来看,我认为在这种情况下使用同步请求会有些具有误导性,因为这表明呼叫具有顺序性,即使没有。从编写一系列不依赖于彼此的异步请求的角度来看,这应该不会太糟糕,因为您只需设置一个计数器,进行所有调用,在每个回调中递增计数器,您就完成了当计数器等于您拨打的电话数时。

更新:@rbrundritt在对此答案的评论中做出了非常有趣且相关的观察:

我发现与网络工作者一起工作的一件事是,他们似乎每个人都获得了自己的 http 限制。浏览器将并发 http 请求的数量限制在 8 或 12 左右,具体取决于限制之前的浏览器,如果您有大量请求要处理,这可能是一个瓶颈。我发现如果我通过我的请求网络工作者,每个人可以在开始节流之前执行 8 到 12 个并发请求。对于某些应用程序来说,这可能是一个巨大的好处。

@rbrundritt

于 2012-12-28T12:06:23.843 回答
1

我只是想添加一条注释(对于评论来说太长了),@tiffon 的答案中提到的约 60 名网络工作者的限制似乎不再存在于 Chromium 中。我可以像这样在 Chrome 中创建 500 个工作人员,而不会出现错误/崩溃:

let workers = [];
for(let i = 0; i < 500; i++) {
  let worker = new Worker(URL.createObjectURL(new Blob([`console.log('cool${i}')`])));
  worker.postMessage({});
  workers.push(worker);
}
await new Promise(r => setTimeout(r, 15000));
for(let i = 0; i < workers.length; i++) {
  workers[i].terminate();
}

不过,很难想象有数百名工人是合适的情况,因为目前核心数量并未超过 64 人左右。

于 2019-05-15T09:31:19.957 回答