TypeScript增强的SharedWorker PortMessage通道契约

Jas*_*ban 5 javascript rpc json-rpc web-worker typescript

对于Windows和Workers之间的RPC式通信通道,利用TypeScript语言功能的优秀通用设计是什么?

SharedWorkers是JavaScript代码清单,由浏览器在特定浏览器窗口的上下文之外运行.单个SharedWorker(通过脚本URI)由所有打开的浏览器窗口共享,其自己的代码请求它.Windows和工作人员通过纠缠的worker.port对象进行通信,发送者可以使用postMessage()并且接收者可以从中侦听"消息"事件.允许发布的最一致支持的类型是单个string,可以很容易地JSON.stringify(ofSomeObject)但可以是任何自定义格式.

TypeScript是JavaScript的扩展,它提供了一些有用的类型安全性和其他有用的应用程序代码管理功能.

远程过程调用库(如WCF)使用由通信通道的两个(所有)方共享的SOA样式的Contract接口,并抽象出序列化和反序列化请求的单调且容易出错的必要性.


浏览器Windows与其Worker之间的通信类似于RPC,因为我们无法通过通道将代码作为数据传递.一个主要区别是通信只是单向的.发件人可以发布邮件但不能阻止并等待结果.相反,应用程序层负责将接收的数据与发送的请求进行匹配(如果适用).

为了利用TypeScript的输入功能,在我看来,遵循契约范式是一个不错的选择.我们需要:

  1. 每个接收者的服务合同的一个接口.
  2. 每个合同的接收者实施
  3. 每个合同的代理实施

首先,我们需要教一些关于在lib.d.ts定义上构建的SharedWorkers的TypeScript.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;
}
Run Code Online (Sandbox Code Playgroud)

在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);
Run Code Online (Sandbox Code Playgroud)

代理实现可能具有以下功能:

SessionLogin(username: string) {
    this.worker.port.postMessage(Command('SessionLogin', arguments));
}
Run Code Online (Sandbox Code Playgroud)

消息事件处理程序将接收的参数应用于指定的方法名称.ReceiverImplementation对象应该是独立的,可能来自任何其他类,因为我们希望避免方法名称冲突.也许不是 - 我们在客户端机器上运行的客户端代码之间进行交谈.没有相同的安全问题(也没有执行警卫的能力).

发布整个原型太长/太复杂,因为主题,它不适合jsfiddle.无论如何,我拥有的并不是那么好.对于非常少的功能,它似乎仍然是一堆样板代码.

而且我很确定所有这些都适用于非共享Web工作者,但由于所有这些沟通的麻烦,我没有看到非共享品种的价值主张!

这是一个庞大的问题,但我希望我已经做好了解释它的工作.您对解决此Window-Worker通信的想法是什么?如何利用JavaScript的轻松本质和纯粹的TypeScript安全幻觉来实现更简单,更少出错的通信?我怀疑我正在采用受.NET限制为灵感的WCF,并将它们与JavaScript过于接近.

谢谢.