代码之家  ›  专栏  ›  技术社区  ›  HostileFork says dont trust SE

使用同步xmlhttpRequest从GUI获取数据的工作线程

  •  8
  • HostileFork says dont trust SE  · 技术社区  · 6 年前

    我想要一个 Web Worker 它位于调用堆栈的深处,能够发出同步请求以从GUI获取信息。

    GUI本身没有被阻塞——它能够处理消息。但工作堆栈上的javascript没有写入 async / await 风格。它只是许多同步代码。因此,如果GUI试图用一个后消息将一个响应发送回工作者,那么它将被卡在onmessage()队列中。

    我发现至少有一个黑客可以在今天的浏览器中使用。 工作人员可以将所需信息以及某种ID(例如UUID)发送到GUI。然后它可以生成一个同步的xmlhttprequest-- which is not deprecated on workers --到网络上某个具有该ID的服务器。

    当工作进程正在等待该HTTP请求时,GUI将处理该信息请求。完成后,它会执行xmlhttpRequest,将ID和数据发布到同一个服务器。然后,服务器使用该信息来完成它为工作人员保持打开状态的阻塞请求。这就满足了同步请求。

    将图形用户界面和工作人员之间的同步外包到服务器上似乎有些鲁莽。但如果必须的话我会做的,因为 它不适合用于强制以异步方式编写工作代码的用例。 另外,我假设 总有一天 浏览器将能够进行这种本地同步。但它看起来像是一个可以使用的机制-- SharedArrayBuffer ,已暂时禁用。

    更新日期:2018年底: sharedraybuffer是 re-enabled in Chrome for desktop v67 . 它不是为了 Android Chrome or other browsers yet 可能会有一段时间。

    (更奇怪的选择,比如 compiling a JavaScript interpreter into the worker 因此,JS堆栈可以被挂起并随意重新启动,而不在表中,这不仅是由于其大小和性能,而且还因为无法使用浏览器的开发人员工具调试工作人员。)

    所以…

    • 同步xmlhttpRequest是否有任何方法被愚弄,从而对来自浏览器本身的某个内容发出请求(可能通过自定义链接方案?)如果GUI线程可以直接回答一个XMLHttpRequest,这将切断中间人。

    • 可以通过某种插件提供相同的功能吗?我在想也许同步可以作为一个抽象来完成。如果有人没有这个插件,那么它会退回到使用网络作为同步代理。 (假设他们重新启用sharedraybuffer,它就可以使用它。)

    我还想知道是否有某种stock-js-ready服务已经实现了echo服务器的协议…如果有人知道的话。似乎很容易写。

    2 回复  |  直到 6 年前
        1
  •  1
  •   Louis    6 年前

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

    服务工人和 fetch

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

    注意, 取来 API和关联的事件不是 具体的 为工人提供服务 取来 在普通工人或其他地方,如果它解决了你的问题。你经常看到 取来 与服务工人一起提到,因为服务工人可以用于不能使用常规工人的场景,其中一些场景需要提供自定义响应 取来 请求。

    假xmlhttpRequest

    Marinos An建议 comment 使用假xmlhttpRequest对象。 在大多数情况下 那就行了。Sinon这样的测试框架提供了假xmlhttpRequest,允许测试代码完全控制被测试代码得到的响应。但是,它不适用于您的用例场景。如果您的伪XHR实现是作为一个javascript对象实现的,并且您尝试将其发送给工作者,那么工作者将得到它的完整克隆。对在工人内部执行的伪造XHR的操作不会在工人外部看到。对在工人外部执行的伪造XHR的操作不会在工人内部看到。

    理论上,可以通过让假XHR包含两个对象来解决克隆问题:一个前端用于执行请求,另一个后端用于建立假响应。您可以将前端发送给工作人员,但前端和后端必须相互通信,这将使您回到您试图解决的通信问题。如果您可以让伪造的XHR的两个部分以一种允许您伪造同步XHR请求的方式相互交谈,那么 出于同样的原因 如果没有伪造的XHR,您就能够解决通信问题。

        2
  •  0
  •   Felipe N Moura    6 年前

    嗯……也许你可以在飞行中创造你的工人,就像这样。

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

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

    const w1 = startNewWorker(yourCodeThatDoesSomething);
    w1.onmessage = function () { /* ... */};
    
    const w2 = startNewWorker(yourCodeThatDoesSomething);
    w2.onmessage = function () { /* ... */};
    

    这两者都是异步的,不会为您的用户阻塞接口,并且它们都能够完成自己的工作,并且每个都有自己的监听器。

    注意到 code 是一个 一串 ,因此,如果您有函数,可以使用它 .toString() 与连接 () ,如下所示:

    function myWorkerContent () {
      // do something ....
    }
    
    const code = "(" + myWorkerContent.toString() + ")()";
    // or, if you want to use templateLiterals
    // const code = `(${myWorkerContent.toString()})()`;
    

    这样,当运行您的工作人员时,它将在您的每个工作人员内部立即创建和执行该功能。