我希望一个深入调用堆栈的Web Worker能够发起同步请求以从GUI获取信息。
GUI本身没有被阻塞 - 它能够处理消息。但是,工作线程堆栈上的JavaScript并没有采用async / await风格编写。它只是大量的同步代码。因此,如果GUI尝试使用postMessage向工作线程发送响应,那么该响应将会被卡在onmessage()队列中。 我至少找到了一种在今天的浏览器中有效的方法。工作线程可以向GUI发送postMessage以获取所需信息,并附带某种ID(例如UUID)。然后,它可以通过不会在工作线程中被弃用的同步XMLHttpRequest向外部网络服务器发送带有该ID的请求。
当工作线程等待http请求时,GUI处理信息请求。完成后,它将进行XMLHttpRequest以POST到同一服务器,并提供ID和数据。然后,服务器使用该信息来满足其保持对工作线程开放的阻塞请求。这样就满足了同步请求。
似乎将GUI和工作线程之间的同步外包给服务器有些脑残。但如果必须这样做,我会这样做,因为强制工作线程代码采用异步方式不适合使用情况。此外,我假设将来浏览器将能够本地执行这种同步。但看起来可以使用的唯一机制SharedArrayBuffer,已经暂时被禁用。
GUI本身没有被阻塞 - 它能够处理消息。但是,工作线程堆栈上的JavaScript并没有采用async / await风格编写。它只是大量的同步代码。因此,如果GUI尝试使用postMessage向工作线程发送响应,那么该响应将会被卡在onmessage()队列中。 我至少找到了一种在今天的浏览器中有效的方法。工作线程可以向GUI发送postMessage以获取所需信息,并附带某种ID(例如UUID)。然后,它可以通过不会在工作线程中被弃用的同步XMLHttpRequest向外部网络服务器发送带有该ID的请求。
当工作线程等待http请求时,GUI处理信息请求。完成后,它将进行XMLHttpRequest以POST到同一服务器,并提供ID和数据。然后,服务器使用该信息来满足其保持对工作线程开放的阻塞请求。这样就满足了同步请求。
似乎将GUI和工作线程之间的同步外包给服务器有些脑残。但如果必须这样做,我会这样做,因为强制工作线程代码采用异步方式不适合使用情况。此外,我假设将来浏览器将能够本地执行这种同步。但看起来可以使用的唯一机制SharedArrayBuffer,已经暂时被禁用。
2018年底左右更新: SharedArrayBuffer在Chrome桌面版v67中被重新启用。但是在Android Chrome或其他浏览器上还没有恢复,并且可能需要一段时间。
(更奇怪的选项,比如将JavaScript解释器编译到worker中,以便可以随意暂停和重新启动JS堆栈,这些不在讨论范围内--不仅因为大小和性能,而且由于无法使用浏览器的开发工具调试worker。)
所以...
有没有办法欺骗同步XMLHttpRequest,使其请求来自浏览器内部的东西(也许通过自定义链接方案?)如果GUI线程可以直接回答XMLHttpRequest,那就可以省去中间人。
是否可以通过某种插件提供相同的功能?我想也许可以将同步作为一个抽象层来完成。如果某些人没有该插件,则会退回到使用网络作为同步代理。(并且假设他们重新启用SharedArrayBuffer,它只能使用它。)
我还想知道是否有一些JS-ready服务实现了回声服务器的协议...如果有人知道的话。似乎很容易写。
fetch
事件来提供自定义响应。据我所知,只有在您实际使用fetch
API时才会生成它。xhr不会生成fetch
事件。而且,您不能仅仅因为fetch
不支持同步操作就在特定情况下使用fetch
代替xhr。规范中提到了一个“同步标志”,但它不是API的一部分。 - Louis