如何在未来包装 Web Worker 响应消息?
How to wrap Web Worker response messages in futures?
请考虑一个 scala.js 应用程序,它在浏览器中运行,由一个主程序和一个 web worker 组成。
主线程通过传递包含方法名称和调用它们所需的参数的消息,将长 运行 操作委托给网络工作者。 worker 将方法 return 值以响应消息的形式传回主线程。
简单来说,这个程序抽象了 web worker 消息传递,以便主线程中的代码可以使用惯用的异步 Scala 语法调用工作线程中的方法。
因为网络工作者不以任何方式将消息与其响应相关联,抽象依赖于注册中心,一个中间对象,它管理每个跨上下文方法调用以将调用与结果相关联。这个单例也可以绑定回调函数,但是有没有办法用 futures 而不是回调来完成这个?
如何在此注册表上构建一个抽象,以允许程序员将其与 Scala 中的标准异步编程结构一起使用:futures 和 promises?
我应该如何编写此功能,以便 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 worker 的响应意味着未来的完成。有没有一种方法可以编写将其完成状态委托给外部流程的自定义未来?有没有其他方法可以link web worker 对未来状态的响应消息?
Can/Should 我扩展了 Future 特性?这在 Scala.js 中可能吗?我应该扩展一个具体的 class 吗?是否有其他方法可以将这些跨上下文 Web 工作者方法调用封装到现有的异步 Scala 功能中?
感谢您的考虑。
嗯。只是在这里吐口水(我还没有使用过 worker),但在你工作的单线程 JavaScript 世界中,将请求与 Future 关联起来似乎相当容易。
这是一个假设的设计。假设每个给工人的 request/response 都会自动包裹在一个信封中;信封包含一个 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 一样简单......
请考虑一个 scala.js 应用程序,它在浏览器中运行,由一个主程序和一个 web worker 组成。
主线程通过传递包含方法名称和调用它们所需的参数的消息,将长 运行 操作委托给网络工作者。 worker 将方法 return 值以响应消息的形式传回主线程。
简单来说,这个程序抽象了 web worker 消息传递,以便主线程中的代码可以使用惯用的异步 Scala 语法调用工作线程中的方法。
因为网络工作者不以任何方式将消息与其响应相关联,抽象依赖于注册中心,一个中间对象,它管理每个跨上下文方法调用以将调用与结果相关联。这个单例也可以绑定回调函数,但是有没有办法用 futures 而不是回调来完成这个?
如何在此注册表上构建一个抽象,以允许程序员将其与 Scala 中的标准异步编程结构一起使用:futures 和 promises?
我应该如何编写此功能,以便 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 worker 的响应意味着未来的完成。有没有一种方法可以编写将其完成状态委托给外部流程的自定义未来?有没有其他方法可以link web worker 对未来状态的响应消息?
Can/Should 我扩展了 Future 特性?这在 Scala.js 中可能吗?我应该扩展一个具体的 class 吗?是否有其他方法可以将这些跨上下文 Web 工作者方法调用封装到现有的异步 Scala 功能中?
感谢您的考虑。
嗯。只是在这里吐口水(我还没有使用过 worker),但在你工作的单线程 JavaScript 世界中,将请求与 Future 关联起来似乎相当容易。
这是一个假设的设计。假设每个给工人的 request/response 都会自动包裹在一个信封中;信封包含一个 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 一样简单......