原文链接:https://github.com/Microsoft/napajs/blob/master/docs/api/transport.md
Namespace transport
Table of Contents
-
Introduction
- Transportable types
- Constructor ID
- Transport context
- Transporting functions
-
API
- isTransportable(jsValue: any): boolean
- register(transportableClass: new(...args: any[]) => any): void
- marshall(jsValue: any, context: TransportContext): string
- unmarshall(json: string, context: TransporteContext): any
- class TransportContext
- context.saveShared(object: memory.Shareable): void
- context.loadShared(handle: memory.Handle): memory.Shareable
- context.sharedCount: number
- interface Transportable
- transportable.cid: string
- transportable.marshall(context: TransportContext): object
- transportable.unmarshall(payload: object, context: TransportContext): void
- abstract class TransportableObject
- transportableObject.cid: string
- transportableObject.marshall(context: TransportContext): object
- transportableObject.unmarshall(payload: object, context: TransportContext): void
- abstract transportableObject.save(payload: object, context: TransportContext): void
- abstract transportableObject.load(payload: object, context: TransportContext): void
- decorator cid
介绍
已有的JavaScript引擎不支持在多个虚拟机之间运行JavaScript,也就是说每一个虚拟机单独管理自己的堆栈。虚拟机之间传递的数据必须被封装和拆封。载荷的大小和对象的复杂度将严重影响通信效率。而在Napa中,我们尝试设计一种模式高效的实现对象共享,而这种模式是基于JavaScript虚拟机(也就是worker)都位于同一个进程,而且原生对象能够被封装成JavaScripts对象对外暴露。
为实现这个模式而引入了下面这些概念:
可传递类型
可传递类型是JavaScript类型中可以在Napa worker间被显式地传递和分享的数据类型。它们作为值类型传递给broadcast和execute的入参,也通过set和get方法共享键值对对象。
可传递类型是:
- JavaScript 原始类型:null,boolean,number,string
- 实现了可传递接口的对象
- 数组或由上述类型组成的简单JavaScript对象
- 未引用闭包的方法
构造函数ID (cid)
对于实现了可传递接口的用户自定义类,Napa从字符串载荷中使用构造函数ID(cid)来查找构造函数创建正确的对象。cid被封装后作为有效载荷的一部分。在解封时,传输层会提取到cid并调用相关的构造函数创建对象实例,然后在这个对象上调用解封函数。
开发者为自定义的类选择合适的cid,为避免冲突,建议使用模块id和类名的组合作为cid。在使用带有装饰器功能的TypeScript时,开发者可以使用类装饰器cid自动注册用户可传递类。或者在模块初始化时手动调用transport.register来将用户自定义的类注册为可传递类。
传递上下文
因为有多种不能以序列化形式保存和加载的状态(比如std::shared_ptr),或者序列化是非常低效的(比如JavaScript方法)。引入传递上下文来解决这些问题。传递上下文对象可以在JavaScript虚拟机之间传递,也可以存储在本地内存,可以通过使用传递上下文延长共享的本地对象的生命周期。通过可传递上下文实现的可传递实例是可共享包。
传递方法
通过将它的定义封装在store里,JavaScript 方法就成了特殊的可传递类型,可以在目标线程上生成一个新方法。
可传递函数的重点是:
对同一个函数,在每个JavaScript线程上只做一次封装/解封。一旦一个方法已经被传递进来了,后续同一个函数被再次传入之前的JavaScript线程将不再耗费资源。 闭包不能被传递,但当传递的是一个函数时不会报错。实际上,当你在后续使用传入的这个方法时,会抛出运行时错误提示来自闭包里的一个变量未定义。
在传入的方法中可以访问到 __dirname / __filename,这是由方法的origin属性所决定的。默认的origin属性被设置为当前工作路径。
API
isTransportable(jsValue: any): boolean
该方法可以区别一个JavaScript值是否是可传递类型。
// JS primitives
assert(transport.isTransportable(undefined));
assert(transport.isTransportable(null));
assert(transport.isTransportable(1));
assert(transport.isTransportable('string'));
assert(transport.isTransportable(true));
// Transportable addon
assert(transport.isTransportable(napa.memory.crtAllocator));
// Composite of transportable types.
assert(transport.isTransportable([
1,
"string",
{ a: napa.memory.crtAllocator }
]));
class B {
field1: number;
field2: string;
}
// Not transportable JS class. (not registered with @cid).
assert(!transport.isTransportable(new B()));
register(transportableClass: new(...args: any[]) => any): void
该方法可以在传输层封装/解封类的实例之前将该类注册成一个可传输类。用户也可以使用类装饰器@cid注册类。 例如: class A extends transport.AutoTransportable { field1: string, method1(): string { return this.field1; } }
// Explicitly register class A in transport.
transport.register(A);
marshall(jsValue: any, context: TransportContext): string
该方法将JavaScript 值根据其TransportContext封装到JSON载荷中。如果该值不可传递,则会抛错。 例如: var context = transport.createTransportContext(); var jsonPayload = transport.marshall( [1, 'string', napa.memory.crtAllocator], context); console.log(jsonPayload);
unmarshall(json: string, context: TransportContext): any
该方法根据TransportContext将JSON载荷解封装为可传递的JavaScript值。如果cid属性存在但没有在传输层注册,则将会抛错。 例如: var value = transport.unmarshall(jsonPayload, context);
TransportContext类
在封装/解封期间,可传递上下文类存储了已共享的指针和方法。
context.saveShared(object: memory.Shareable): void
保存可共享对象
context.loadShared(handle: memory.Handle): memory.Shareable
加载上下文可共享的对象
context.sharedCount: number
统计当前上下文的可共享对象数量。
Transportable 接口
可传递对象的接口
transportable.cid: string
该接口可以访问 Constructor ID。用来查看当前当前类的载荷的构造器。
transportable.marshall(context: TransportContext): object
在TransportContext的协助下,将对象被封装转化成一个简单的JavaScript对象。
transportable.unmarshall(payload: object, context: TransportContext): void
将已封装的载荷解封转化成当前对象。
TransportableObject抽象类
TBD
装饰器 cid
TBD