上一篇:Theia APIs——事件html
import { ContainerModule } from 'inversify'; import { ConnectionHandler, JsonRpcConnectionHandler } from "../../messaging/common"; import { ILoggerServer, ILoggerClient } from '../../application/common/logger-protocol'; export const loggerServerModule = new ContainerModule(bind => { bind(ConnectionHandler).toDynamicValue(ctx => new JsonRpcConnectionHandler<ILoggerClient>("/services/logger", client => { const loggerServer = ctx.container.get<ILoggerServer>(ILoggerServer); loggerServer.setClient(client); return loggerServer; }) ).inSingletonScope() });
咱們來詳細看一下:前端
import { ConnectionHandler, JsonRpcConnectionHandler } from "../../messaging/common";
import { MessageConnection } from "vscode-jsonrpc"; export const ConnectionHandler = Symbol('ConnectionHandler'); export interface ConnectionHandler { readonly path: string; onConnection(connection: MessageConnection): void; }
import { ILoggerServer, ILoggerClient } from '../../application/common/logger-protocol';
文件logger-protocol.ts包含了服務器和客戶端須要實現的接口。node
bind<ConnectionHandler>(ConnectionHandler).toDynamicValue(ctx => {
constructor( @inject(ContributionProvider) @named(ConnectionHandler) protected readonly handlers: ContributionProvider<ConnectionHandler>) { } onStart(server: http.Server): void { for (const handler of this.handlers.getContributions()) { const path = handler.path; try { createServerWebSocketConnection({ server, path }, connection => handler.onConnection(connection)); } catch (error) { console.error(error) } } }
new JsonRpcConnectionHandler<ILoggerClient>("/services/logger", client => {
咱們來看看這個類的實現作了哪些事情:webpack
export class JsonRpcConnectionHandler<T extends object> implements ConnectionHandler { constructor( readonly path: string, readonly targetFactory: (proxy: JsonRpcProxy<T>) => any ) { } onConnection(connection: MessageConnection): void { const factory = new JsonRpcProxyFactory<T>(this.path); const proxy = factory.createProxy(); factory.target = this.targetFactory(proxy); factory.listen(connection); } }
onConnection(connection: MessageConnection): void { const factory = new JsonRpcProxyFactory<T>(this.path); const proxy = factory.createProxy(); factory.target = this.targetFactory(proxy); factory.listen(connection);
咱們一行一行來看:git
const factory = new JsonRpcProxyFactory<T>(this.path);
上面這一行在路徑"/services/logger"上建立了一個JsonRpcProxy。github
const proxy = factory.createProxy();
而後,咱們從工廠建立了一個代理對象,它將使用ILoggerClient接口來調用JSON-RPC鏈接的另外一端。web
factory.target = this.targetFactory(proxy);
上面這一行將調用咱們在參數中傳遞的函數,因此:express
client => { const loggerServer = ctx.container.get<ILoggerServer>(ILoggerServer); loggerServer.setClient(client); return loggerServer; }
factory.listen(connection);
'/services/*': { target: 'ws://localhost:3000', ws: true },
import { ContainerModule, Container } from 'inversify'; import { WebSocketConnectionProvider } from '../../messaging/browser/connection'; import { ILogger, LoggerFactory, LoggerOptions, Logger } from '../common/logger'; import { ILoggerServer } from '../common/logger-protocol'; import { LoggerWatcher } from '../common/logger-watcher'; export const loggerFrontendModule = new ContainerModule(bind => { bind(ILogger).to(Logger).inSingletonScope(); bind(LoggerWatcher).toSelf().inSingletonScope(); bind(ILoggerServer).toDynamicValue(ctx => { const loggerWatcher = ctx.container.get(LoggerWatcher); const connection = ctx.container.get(WebSocketConnectionProvider); return connection.createProxy<ILoggerServer>("/services/logger", loggerWatcher.getLoggerClient()); }).inSingletonScope(); });
其中最重要的幾行:json
bind(ILoggerServer).toDynamicValue(ctx => { const loggerWatcher = ctx.container.get(LoggerWatcher); const connection = ctx.container.get(WebSocketConnectionProvider); return connection.createProxy<ILoggerServer>("/services/logger", loggerWatcher.getLoggerClient()); }).inSingletonScope();
咱們一行一行來看:後端
const loggerWatcher = ctx.container.get(LoggerWatcher);
const connection = ctx.container.get(WebSocketConnectionProvider);
上面這一行得到了一個websocket鏈接,它將被用來建立一個代理。
return connection.createProxy<ILoggerServer>("/services/logger", loggerWatcher.getLoggerClient());
咱們將一個本地對象做爲第二個參數傳入,用來處理來自遠程對象的JSON-RPC消息。有時,本地對象依賴於代理,在代理實例化以前沒法實例化。這種狀況下,代理接口應該實現JsonRpcServer,而本地對象應該做爲客戶端來提供。
export type JsonRpcServer<Client> = Disposable & { setClient(client: Client | undefined): void; }; export interface ILoggerServer extends JsonRpcServery<ILoggerClient> { // ... } const serverProxy = connection.createProxy<ILoggerServer>("/services/logger"); const client = loggerWatcher.getLoggerClient(); serverProxy.setClient(client);
createProxy<T extends object>(path: string, target?: object, options?: WebSocketOptions): T { const factory = new JsonRpcProxyFactory<T>(path, target); this.listen(factory, options); return factory.createProxy(); }
import { loggerServerModule } from 'theia-core/lib/application/node/logger-server-module';
而後將其載入到主容器。
container.load(loggerServerModule);
import { loggerFrontendModule } from 'theia-core/lib/application/browser/logger-frontend-module';
container.load(frontendLanguagesModule);