简介
在实现编辑器debug功能时。前端与Node中间层通信都是通过websocket来实现的。我们都知道websocket的请求与响应可能不在同一时间同一地方触发
. 就拿此次debug功能需求来说 先要调用initialize
事件初始化成功之后再调用SetBreakpoints
事件成功之后才接收stopped
事件,所有的事件调用都存在先后顺序
。具体debug如何实现可以仔细阅读Debug Adapter Protocol文档
实现
接下来就实现串行的websocket请求方法 (类似http中使用await等待这次请求返回再执行后续操作)
发送/请求
可以在于任何地方
,并且同时可以存在同一时间多个相同websocket事件的派发
第一步: 定义一个Client类并且声明requestQueue用于存储每一个ws事件的id
和resolve回调函数
class Client {
// 定义一个Map数据用于存储,发送的ws回调
requestQueue: Map<number, (data: any) => void>;
constructor() {
this.requestQueue = new Map();
}
}
第二步: 在Client类中添加request
方法,该方法为ws请求方法并把这个这次的promise的resolve
与id
建立映射关系,并且存入到requestQueue
中。会在后续的onMessage回调中进行消费
。
TIPS: promise的状态分为三种pending
| rejected
| rejected
.
文章推荐: promise源码实现
request(id, eventName, options) {
// 发送ws请求, 并且将此次id存储到requestQueue,只有当ws服务器有返回本次请求才算完成
return new Promise((resolve) => {
socket.send(eventName, {id, ...options}); // socket事件发送
this.requestQueue.set(id, (data) => {
resolve(data);
});
});
}
第三步: 在Client类中监听message事件,并且消费requestQueue
中的对应数据
constructor() {
...
this.socket.addEventListener("message", (event: MessageEvent<any>) => {
const { data } = event;
const res = JSON.parse(data);
const { id } = res;
if (id !== undefined) {
// 接收到ws服务器返回的事件id,从requestQueue执行对应的resolve相关回调操作
const callback = this.requestQueue.get(id);
callback?.(res);
this.requestQueue.delete(id);
}
});
}
第四步: 调用request
方法编写,使用await
进行等待,这样我们就能实现串行了
// 调用request请求
class test {
private client: Client;
constructor() {
this.client = new Client();
}
async initialize() {
// 执行request请求,request是一个ws的请求
await this.client.request(uuid,"initialize");
await this.client.request(uuid,"SetBreakpoints");
// 执行后续操作...
}
}
第五步: 执行第二步request
请求时有可能服务异常,此时我们可以添加timeOut方法
和结合Promise.race
来实现超时操作
function timeOut(delay: number): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求超时');
}, delay);
});
// 使用
return Promise.race([request(...), _timeOut(2000)]);
总结
以上就是实现websocket串行的全部流程,适用于任何类似于发布订阅模式
类型。关键点就是在发送ws事件时声明一个promise,该promise的完成时机是由接收到服务端响应的message事件触发
推荐文章
推荐如下文章|官网
让你更加理解Promise底层
、debug底层
以及debug和代码补全实现
手写promise源码实现
JavaScript Debugger 原理揭秘
Debug Adapter Protocol
Language Server Protocol