在上一篇文章中,我们分析了VSCode的整体代码结构,了解到VSCode是前后端分离开发的。而且无论前端是基于electron还是web,后端是本地还是云端,调用方式都是一样的。在这样的架构下,前后端之间的通信方式是如何实现的呢?在本文中,我们将探索VSCodeForWeb的进程间通信方式。ProcessCommunicationandCallMode进程间通信协议对于多进程架构的项目,进程间的通信将通过进程间调用(InterProcessCalling,IPC)进行。VSCode设计了专门的IPC模块来实现通信。代码位于src/vs/base/parts/ipc。exportconstenumRequestType{Promise=100,PromiseCancel=101,EventListen=102,EventDispose=103}从枚举类型可以看出,VSCode的IPC模块同时支持两种调用方式,一种是基于调用实现onPromise,还有一个是第一个是通过EventEmitter/Listener的事件监听机制实现的。以事件监听机制为例,VSCode中使用了vscode-jsonrpc包来封装实现,调用方式如下:import*ascpfrom'child_process';import*asrpcfrom'vscode-jsonrpc/节点';让childProcess=cp。spawn(...);//使用标准输入和标准输出进行通信:letconnection=rpc.createMessageConnection(newrpc.StreamMessageReader(childProcess.stdout),newrpc.StreamMessageWriter(childProcess.stdin));letnotification=newrpc.NotificationType('testNotification');connection.listen();connection.sendNotification(notification,'HelloWorld');服务器调用也使用类似的封装:import*asrpcfrom'vscode-jsonrpc/node';letconnection=rpc.createMessageConnection(newrpc.StreamMessageReader(process.stdin),newrpc.StreamMessageWriter(process.stdout));letnotification=newrpc.NotificationType('testNotification');连接。onNotification(notification,(param:string)=>{console.log(param);//这会打印HelloWorld});connection.listen();进程间通信单元用于实现客户端与服务端之间的点对点对于通信,我们需要一个最小单元来调用和监听消息。在VSCode中,这个最小单位是Channel。/***`IChannel`是对一组命令的抽象。*您可以在一个通道上“调用”多个命令,每个命令最多接受一个参数。`call`总是返回一个promise*,最多只有一个返回值。*/exportinterfaceIChannel{call(command:string,arg?:any,cancellationToken?:CancellationToken):Promise;listen(event:string,arg?:any):Event;}每个通信过程都要求客户端和服务器在同一个Channel。在VSCode中,客户端和服务端之间的通信是通过Connection类建立的,连接是通过传入客户端和服务端之间的Channel来实例化的,即ChannelClient和ChannelServer。interfaceConnectionextendsClient{readonlychannelServer:ChannelServer;readonlychannelClient:ChannelClient;}它们的区别在于,由于服务端可以同时服务多个客户端,所以支持多个ChannelsGet,而ChannelClient是一对一的连接。综上所述,我们梳理了VSCode中IPC模块的基本结构,了解了进程间通信的细节。用一张图来总结梳理一下知识点:由于VSCode的IPC模块天生就支持异步能力,实际上并没有区分进程是本地进程还是远程进程。只要是通过Channel进行通信,就可以认为是一个进程间通信,可以复用相同的代码来编写。参考VSCode官方文档VSCodeAPIVSCode源码解读--IPC通信机制vscode源码解析-进程间调用