对于 Windows 和 Worker 之间的 RPC 样式的通信通道,利用 TypeScript 语言功能的良好通用设计是什么?
SharedWorkers是由浏览器在特定浏览器窗口上下文之外运行的 JavaScript 代码列表。一个 SharedWorker(通过脚本 URI)被所有打开的浏览器窗口共享,它们自己的代码请求它。worker.port
Windows 和工作线程通过发送者可以 postMessage() 和接收者可以监听“消息”事件的纠缠对象进行通信。允许发布的最一致支持的类型是单一的string
,它可以很容易地成为JSON.stringify(ofSomeObject)
但可以是任何自定义格式。
TypeScript是 JavaScript 的扩展,它提供了一些有用的类型安全和其他有用的应用程序代码管理功能。
远程过程调用库(如 WCF)使用由通信通道的(所有)双方共享的 SOA 样式的合同接口,并抽象出单调且容易出错的序列化和反序列化请求的必要性。
浏览器 Windows 和它们的 Worker 之间的通信类似于 RPC,因为我们不能通过通道将代码作为数据传递。一个主要区别是通信是单向的。发件人可以发布消息,但不能阻止并等待结果。相反,应用层负责将接收到的数据与发送的请求进行匹配(如果合适)。
为了利用 TypeScript 的打字特性,在我看来遵循 Contract 范式是一个不错的选择。我们需要:
- 每个接收者的服务合约都有一个接口。
- 每个合约的接收者实现
- 每个合约的代理实现
首先,我们需要向 TypeScript 介绍基于 lib.d.ts 定义构建的 SharedWorkers。SharedWorker.d.ts:
interface ConnectEvent extends Event {
ports: MessagePort[];
};
interface SharedWorker extends EventTarget, AbstractWorker {
port: MessagePort;
};
declare var SharedWorker: {
prototype: SharedWorker;
new (scriptURL: any, name: any): SharedWorker;
new (scriptURL: any): SharedWorker;
}
在 WCF 中,我们有一个环境 OperationContext 来了解连接的客户端。在大多数情况下,我们还会返回一个值来发送对请求的响应。
在 JavaScript 中,我们没有 ThreadStatic,我怀疑我们能否可靠地提供 OperationContext 的环境等价物。(每个代码清单都是单线程运行的,但是异步方式是通过计时器回调实现的,并且可能由 Worker 实现使用,我认为我们无法正确跟踪它。)
使用 MessagePorts,我们无法返回值。相反,我们必须向请求者发送另一个单向响应,因此我们需要返回 MessagePort 的句柄。但是,此返回 MessagePort 不能是 Contact 的一部分,因为 Proxy 实现不需要它。我所能想到的就是创建一个新的实现类实例,该实例使用接收器/代理特定的差异进行初始化,例如返回的 MessagePort 和任何其他数据,例如所有连接的用于广播消息的 MessagePort 的数组。然后实现的成员方法可以引用它们,因为它们可能是 OperationContext。
以及消息事件处理程序的示例:
worker.port.addEventListener('message', (e: MessageEvent) => {
var data = JSON.parse(e.data);
new ReceiverImplementation(worker.port)[data.name].apply(this, data.params);
}, false);
代理实现可能具有以下功能:
SessionLogin(username: string) {
this.worker.port.postMessage(Command('SessionLogin', arguments));
}
消息事件处理程序将接收到的参数应用于指定的方法名称。ReceiverImplementation 对象应该如图所示独立于任何其他类,因为我们希望避免方法名称冲突。也许不是——我们正在谈论在客户端机器上运行的客户端代码。没有相同的安全问题(也没有执行警卫的能力)。
发布整个原型太长/太复杂,并且由于主题,它不适合 jsfiddle。无论如何,我所拥有的并不是那么好。它看起来仍然像一堆样板代码,功能很少。
而且我很确定所有这些也适用于非共享网络工作者,但是由于沟通的所有这些麻烦,我看不到非共享品种的价值主张!
这是一个庞大的问题,但我希望我在解释它方面做得很好。你对解决这个 Window-Worker 通信有什么想法?如何利用 JavaScript 的轻松性质和 TypeScript 的安全假象来实现更简单且不易出错的通信?我怀疑我正在采用 .NET-limitations-inspired WCF 并将它们过于接近地移植到 JavaScript。
谢谢。