【发布时间】:2018-10-08 15:31:37
【问题描述】:
我想要一个位于调用堆栈深处的Web Worker,以便能够发出同步请求以从 GUI 获取信息。
GUI 本身没有被阻止——它能够处理消息。但是worker栈上的JavaScript不是用async / await风格写的。它只是很多同步代码。因此,如果 GUI 尝试使用 postMessage 将响应发送回工作人员,那只会卡在 onmessage() 队列中。
我发现了至少一种适用于当今浏览器的 hack。 工作人员可以将消息发布到 GUI 以获取所需的信息 - 以及某种 ID(例如 UUID)。然后它可以向网络上具有该 ID 的某个服务器发出同步 XMLHttpRequest--which is not deprecated on workers--。
当工作人员等待该 http 请求时,GUI 会处理信息请求。完成后,它会执行 XMLHttpRequest 以 POST 到具有 ID 和数据的同一服务器。然后,服务器使用该信息来满足它对工作人员开放的阻塞请求。这满足了同步请求。
将 GUI 和 worker 之间的同步外包给服务器似乎有点愚蠢。但如果必须,我会这样做,因为它不适合强制工作代码以异步方式编写的用例。另外,我假设总有一天 浏览器将能够在本地进行这种同步。但看起来可以使用的一种机制——SharedArrayBuffer,暂时被禁用了。
大约在 2018 年底更新: SharedArrayBuffer 是 re-enabled in Chrome for desktop v67。 Android Chrome or other browsers yet 没有恢复,可能需要一段时间。
(更多奇怪的选项,如 compiling a JavaScript interpreter into the worker,因此 JS 堆栈可以随意暂停和重新启动 - 不仅因为大小和性能,还因为无法使用浏览器的开发者工具。)
所以...
有什么方法可以让同步 XMLHttpRequest 被愚弄,从浏览器本身发出请求(可能是通过自定义链接方案?)如果 GUI 线程可以直接回答 XMLHttpRequest 会切断退出中间人。
是否可以通过某种插件提供相同的功能?我在想也许同步可以作为一种抽象来完成。如果有人没有插件,它会退回到使用网络作为同步代理。 (大概如果他们重新启用 SharedArrayBuffer,它就可以使用它。)
我也想知道是否有某种股票 JS-ready 服务已经实现了回显服务器的协议......如果有人知道的话。看起来很容易写。
【问题讨论】:
-
“有什么方法可以让同步的 XMLHttpRequest 被愚弄,从浏览器本身发出请求”。你的意思是模拟同步
XMLHttpRequest?例如jsfiddle.net/07nvgrt8/17 ? -
@MarinosAn 我没有看到像这样的模拟对 OP 试图做的事情起作用。问题是相同的模拟对象必须同时存在于启动worker的脚本和worker中。好的,所以您只需将模拟发送给工人,对吗?好吧,不,因为传递给工人的对象是克隆的。因此,在工作人员内部的模拟上提出的任何请求都不会被工作人员外部的模拟看到。
-
@Louis 有人建议我看看"service workers",这与普通工人不同,是supported in most browsers。我没有听说过他们,但我不知道他们是否会给桌子带来任何新东西——在我看来,他们充其量可能会允许一个人对工人做一个自旋锁(坏的)并使用Service Worker 进行中继。还没有完全理解它,希望lazyweb能帮助我。 :-)
-
@HostileFork 我看到的服务工作者示例提到提供“对请求的自定义响应”,但所有示例都使用
fetch事件来提供自定义响应。 AFAIK,它仅在您实际使用fetchAPI 专门时产生。 xhr 不会生成fetch事件。而且您不能只在特定情况下使用fetch而不是xhr,因为fetch不会同步操作。规范中提到了“同步标志”,但它是not part of the API。 -
@Louis 您的 cmets 帮助我避免浪费时间调查服务人员...所以如果您想在赏金截止日期之前将它们消化成“您不走运”的帖子 (也许你对我描述的 XMLHttpRequest 服务有任何见解,如果你碰巧有的话),如果这是不幸的答案,我会给你积分......!
标签: javascript xmlhttprequest synchronization web-worker