乐趣区

关于javascript:VS-Code-For-Web-深入浅出-进程间通信篇

在上一篇中,咱们一起剖析了 VS Code 整体的代码架构,理解了 VS Code 是由前后端拆散的形式开发的。且无论前端是基于 electron 还是 web,后端是本地还是云端,其调用形式并无不同。

这样的架构下,前后端的通信形式是如何实现的呢?本篇咱们将一起来探索 VS Code For Web 的过程间通信形式。

过程通信与调用形式

过程间通信协议

对于多过程架构的我的项目,过程之间的通信会通过过程间调用 (Inter Process Calling, IPC)。VSCode 中本人设计了专门的 IPC 模块来实现通信。代码位于 src/vs/base/parts/ipc。

export const enum RequestType {
    Promise = 100,
    PromiseCancel = 101,
    EventListen = 102,
    EventDispose = 103
}

从 enum type 能够看出,VSCode 的 IPC 模块同时反对两种调用形式,一种是基于 Promise 的调用实现,另一种是通过 Event Emitter/Listener 的那一套事件监听机制来实现。

以事件监听机制为例,VSCode 中采纳 vscode-jsonrpc 这个包来封装实现,调用形式如下:

import * as cp from 'child_process';
import * as rpc from 'vscode-jsonrpc/node';

let childProcess = cp.spawn(...);

// Use stdin and stdout for communication:
let connection = rpc.createMessageConnection(new rpc.StreamMessageReader(childProcess.stdout),
    new rpc.StreamMessageWriter(childProcess.stdin));

let notification = new rpc.NotificationType<string, void>('testNotification');

connection.listen();

connection.sendNotification(notification, 'Hello World');

服务端调用也采纳相似的包装:

import * as rpc from 'vscode-jsonrpc/node';

let connection = rpc.createMessageConnection(new rpc.StreamMessageReader(process.stdin),
    new rpc.StreamMessageWriter(process.stdout));

let notification = new rpc.NotificationType<string, void>('testNotification');
connection.onNotification(notification, (param: string) => {console.log(param); // This prints Hello World
});

connection.listen();

过程间通信单元

为了实现客户端与服务端之间的点对点通信,咱们须要一个最小单元来实现音讯的调用与监听。在 VSCode 中,这个最小单元即为 Channel

/**
 * An `IChannel` is an abstraction over a collection of commands.
 * You can `call` several commands on a channel, each taking at
 * most one single argument. A `call` always returns a promise
 * with at most one single return value.
 */
export interface IChannel {call<T>(command: string, arg?: any, cancellationToken?: CancellationToken): Promise<T>;
    listen<T>(event: string, arg?: any): Event<T>;
}

每次通信过程,须要客户端与服务端处于同一个 Channel 中。

过程间通信建连

在 VSCode 中,客户端与服务端之间的通信建设是通过 Connection 类来建设,通过传入客户端与服务端的 Channel,即 ChannelClientChannelServer 来实例化连贯。

interface Connection<TContext> extends Client<TContext> {
    readonly channelServer: ChannelServer<TContext>;
    readonly channelClient: ChannelClient;
}

它们之间的区别是,因为服务端能够同时对多个客户端服务,因而反对多个 Channel 的获取,而 ChannelClient 为一对一连贯。

综上,咱们就梳理分明了 VSCode 中 IPC 模块的根本架构,理解了过程间的通信细节。

用一张图总结梳理一下知识点:

因为 VSCode 的 IPC 模块人造反对异步能力,因而事实上它并不辨别过程是本地过程还是远端过程,只有是通过 Channel 通信的,都能够被认为是过程间通信,都能够复用雷同的代码编写。

参考

VSCode 的官网文档

VSCode API

VSCode 源码解读 –IPC 通信机制

vscode 源码解析 – 过程间调用

退出移动版