首页 文章

如何在期货中包装Web Worker响应消息?

提问于
浏览
1

请考虑一个在浏览器中运行的scala.js应用程序,它由一个主程序和一个Web worker组成 .

主线程通过传递包含方法名称和调用它们所需参数的消息,将长时间运行的操作委托给Web worker . worker以响应消息的形式将方法返回值传递回主线程 .

简而言之,该程序抽象Web工作者消息传递,以便主线程中的代码可以用惯用语法和异步Scala语法调用工作线程中的方法 .

因为Web工作者不以任何方式将消息与其响应相关联,所以抽象依赖于注册表,即中间对象,它控制每个交叉上下文方法调用以将调用与结果相关联 . 这个单例也可以绑定回调函数,但有没有办法用期货而不是回调来完成这个?

如何在这个注册表上构建一个抽象,允许程序员将它与Scala中的标准异步编程结构一起使用:期货和承诺?

我应该如何编写这个功能,以便scala程序员可以以规范的方式与它进行交互?例如:

// long running method in the web worker
val f: Future[String] = Registry.ultimateQuestion(42) // async

f onSuccess { case q => println("The ultimate question is: " + q) }

我是期货和承诺的新手,但似乎它们通常在一些执行块终止时完成 . 在这种情况下,从Web工作者接收响应表示将来完成 . 有没有办法编写自定义的未来,将其完成状态委托给外部流程?是否有另一种方法将Web工作者响应消息链接到未来状态?

可以/应该延长未来的特质吗?这可能在Scala.js中吗?我应该扩展一个具体的课程吗?是否有其他方法可以在现有的异步Scala功能中封装这些跨上下文Web工作者方法调用?

谢谢您的考虑 .

1 回答

  • 2

    嗯 . 只是在这里spitballing(我还没有使用过工作者),但似乎在你正在使用的单线程JavaScript世界中将请求与Future联系起来相当容易 .

    这是一个假设设计 . 假设每个对worker的请求/响应都自动包装在一个Envelope中;信封包含RequestId . 所以发送方看起来像(这是伪代码,但真实的):

    def sendRequest[R](msg:Message):Future[R] = {
      val promise = Promise[R]
      val id = nextRequestId()
      val envelope = Envelope(id, msg)
      register(id, promise)
      sendToWorker(envelope)
      promise.future
    }
    

    worker处理msg,将结果包装在另一个Envelope中,结果在主线程中处理回来,例如:

    def handleResult(resultEnv:Envelope):Unit = {
      val promise = findRegistered(resultEnv.id)
      val result = resultEnv.msg
      promise.success(result)
    }
    

    这需要一些填充,并且有些人想到了像 R 这样的类型应该是什么,但是那种轮廓可能会很好地运作 . 如果这是JVM你必须担心各种竞争条件,但在单线程JS世界中它可能就像对请求ID使用自动递增整数一样简单,并存储Promise ......

相关问题