工作人员使用同步XMLHttpRequest从GUI获取数据

时间:2018-07-15 20:26:13

标签: javascript xmlhttprequest synchronization web-worker

我希望深入到调用堆栈中的Web Worker能够发出同步请求,以从GUI获取信息。

GUI本身未被阻止-能够处理消息。但是,工作人员堆栈上的JavaScript并非以async / await样式编写。这只是很多同步代码。因此,如果GUI尝试使用postMessage将响应发送回工作人员,则该响应只会停留在onmessage()队列中。

我发现至少有一种可以在当今浏览器中使用的黑客工具。该工作人员可以将Message发布到GUI,以获取所需的信息-以及某种ID(例如UUID)。然后,它可以向Web上具有该ID的服务器发送同步XMLHttpRequest-which is not deprecated on workers

当工作人员正在等待该http请求时,GUI会处理该信息请求。完成后,它将执行XMLHttpRequest以使用ID和数据将其发布到同一服务器。然后,服务器使用该信息来满足其为工作人员开放的阻止请求。这样就满足了同步请求。

将GUI与工作程序之间的同步外包给服务器似乎很麻烦。但是我必须这样做,因为它不适合用于强制以异步方式编写工作代码的用例。另外,我假设 someday < / em>浏览器将能够本地执行这种同步。但是,似乎可以使用的一种机制-SharedArrayBuffer暂时已被禁用。

  

大约在2018年末更新: SharedArrayBuffer为re-enabled in Chrome for desktop v67Android Chrome or other browsers yet尚未恢复正常,可能需要一段时间。

(更多奇怪的选项,例如compiling a JavaScript interpreter into the worker,因此可以随意暂停和重新启动JS堆栈-不仅是由于大小和性能,还在于无法使用浏览器的开发人员工具。)

所以...

  • 是否有任何方法可以欺骗同步XMLHttpRequest来请求来自浏览器内部的某些请求(也许通过自定义链接方案?)如果GUI线程可以直接回答XMLHttpRequest会被切断中间人。

  • 是否可以通过某种插件提供相同的功能?我想也许同步可以作为抽象来完成。如果某人没有该插件,则它会退回到使用网络作为同步代理。 (并且大概是如果他们重新启用了SharedArrayBuffer,就可以使用它。)

我也想知道是否有某种已经支持JS的股票就绪服务,该服务已经实现了回显服务器的协议...如果有人知道的话。似乎很容易写。

2 个答案:

答案 0 :(得分:1)

我看不到有办法去做你想做的事情。最初看起来很有希望的方法最终会遇到难题。

服务人员和fetch

在评论中,您建议服务人员作为可能的解决方案。我看到的服务人员示例提到提供“对请求的自定义响应”。但是,所有示例都使用fetch事件来提供自定义响应。 AFAIK,仅当您实际使用fetch API时才产生。 xhr不会生成获取事件。 (是的,我已经尝试过了,但是它没有用。)而且您不能仅在特定情况下使用fetch而不是xhr,因为获取不能同步运行。 fetch的规范提到了“同步标志”,但它是not part of the API

请注意,fetch API和关联的事件不是服务工作者专用的 ,因此,如果解决了您的问题,您可以在普通工作者或其他地方使用fetch问题。您经常会看到服务工作者提到fetch,因为服务工作者可用于无法使用常规工作者的场景,并且其中某些场景需要为fetch请求提供自定义响应。

伪造的XMLHttpRequest

Marinos在comment中使用伪造的XMLHttpRequest对象的建议。 在大多数情况下,这是可行的。诸如Sinon之类的测试框架提供了伪造的XMLHttpRequest,使测试代码可以完全控制被测代码获得的响应。但是,它不适用于您的用例方案。如果您将伪造的xhr实现实现为一个JavaScript对象,并且尝试将其发送给工作程序,则工作程序将获得它的完整克隆。在工作人员内部执行的对假Xhr的操作不会在工作人员外部看到。在工作人员外部执行的对假XHR的操作不会在工作人员内部看到。

从理论上讲,可以通过使伪造的xhr由两个对象组成来解决克隆问题:通过其执行请求的前端,以及通过其建立伪造响应的后端。您可以将前端发送给工作人员,但是前端和后端必须相互通信,这使您可以直接回到要解决的通信问题。如果您可以使伪造的xhr的两个部分以允许您伪造同步xhr请求的方式相互通信,那么使用同一令牌,您将能够解决通信问题而无需假xhr。

答案 1 :(得分:0)

嗯...也许您可以像这样即时创建自己的工人

<table>
  <tr>
    <td rowspan="2">Corina</td>
    <td>Lydia</td>
    <td rowspan="2">Reinas</td>
    <td colspan="2">Elise</td>
    <td rowspan="2">Vegerra</td>
  </tr>
  <tr>
    <td rowspan="2">Agapi</td>
    <td>Amira</td>
    <td rowspan="2">Filipa</td>
  </tr>
  <tr>
    <td>Daisy</td>
    <td colspan="2">Josephine</td>
    <td>Amarylis</td>
  </tr>
</table>

然后,对于您需要的每个新的http请求,请启动其自己的工作程序:

function startNewWorker (code) {
  var blob = new Blob([code], {type: "application/javascript"});
  var worker = new Worker(URL.createObjectURL(blob));
}

这两者都是异步的,不会为您的用户阻塞接口,他们俩都可以做自己的工作,并且每个人都有自己的侦听器。

请注意,const w1 = startNewWorker(yourCodeThatDoesSomething); w1.onmessage = function () { /* ... */}; const w2 = startNewWorker(yourCodeThatDoesSomething); w2.onmessage = function () { /* ... */}; string ,因此,如果您有函数,则可以将code.toString()串联使用,如下所示:< / p>

()

这样,在运行工作程序时,它将立即在您的每个工作程序内创建并执行功能。