这个项目适用于所有的node.js程序.本文不涉及任何Puppeteer的内容.
因为最近很长一段时间的工作内容都是用Puppeteer
框架分析数据.
有一种经常性的需求是: 在程序工作的中间环境 试验新的代码.eg:
某个页面希望执行 自动点击键入命令
,但是这个过程非常依赖前面的流程,耗时不短.
每每被打断思路,效率低下.
所以希望实现:
在Puppeteer工作时 随时插入 测试 即时 执行代码.
使用控制台来控制程序也尝试过,有两个原因让我放弃这个方案:
其实原因在于命令行窗口作为Log输出,一个平面无法区分更多数据.
所以对 输出数据
,输入数据
,命令
采取多通道的需求 就诞生了.
网页作为数据显示平面是我首先想到的。
但是这个功能说大不大,说小又没底.所以一直搁浅,直到最近客户提出 无法区分两个项目Puppeteer实例.
又恰逢两个项目的间隙,开始动手.
功能点:
因为有: KD-RPC
,P2PManager
,Canvas远程控制系统
的设计经验,所以核心直奔数据结构设计:
因为要打日志,所以初步设计成这样:
Rep =XX=> 网页端
Rep <=cmd=网页端
interface IF_DB{
serviceNumber:number,//这是往总控上设计,独立的服务其实不必要这个
data:{
name: 日志
type:{
main:图片文本,
附属:屏幕等
}
time:Rep运行到现在的时间
data:any
}
}
interface cmd{
name: 即时执行函数
data: any //字符串代码
}
通过什么方式区分不同的返回数据呢?
当然是 通道
,可以为每种特别的数据通道:
服务端发送 客户端监听的通道有三个:
客户端发送 服务端监听的通道有:
cmd
之前分析某款通讯软件的Web版时,其使用的WebSocket给我留下了很深的印象.
从网上找了一些现成的代码,作为基础,使用Socket.IO
库.
这里记录一下node.js是如何断开websocket的:
服务端发送一个CloseConnect事件,这个链接在执行完这一需求后,会自动断开.
客户端则是直接socket.close()
//不太记清,具体是不是这个函数自行打印对象验证.
当我们将一段代码 从网页端输入 传输回 node.js 后,怎么执行呢?
console.log('Hello')
直接let ret = await eval(cmdString)
即可.
为什么有异步? 因为我们要执行异步代码:
例如远程输入:
cmdString =
async sleep(ms){
return new Promise((reslove)=>{
setTimeout(()=>{reslove()},ms)
})
}
function async run(){
console.log('1')
await sleep(5000)
console.log('2')
}
有了await,eval会等待整个代码(包括异步)执行完毕.
玩法也很简单,但难点其实是时机:
什么时候调用Trap?需要用户自己埋点吗?
答案是No! 直接将 将我们整个系统埋入 log中即可.这样每次log都会有一个时机.
暂停命令
其实就是轮循,额额或许是因为我这边不太掌握更多node.js的事件.
不需要,因为node.js是单线程.又需要,因为我们的远程代码可能也有异步代码.
不暂停,可能会造成 远程命令和本地代码交替执行.
好了,网页拿到数据拿到后怎么显示就是 前端的设计了.
效果很6.让停就停,让走就走.想执行就执行,写错代码也没关系.
之前曾经尝试让后台引入 websocket 实现控制,通过这次项目,遇到类似需求,可以用node.js在服务器上做代理.
既然网页端搞成了 代码输入端,不加个高亮,语法分析说不过去.
Monaco Editor
直接使用了其Github范例做基础.
结果我在其它地方 appendChild 方式添加的 socket.io
不能工作了。
monaco 异常提示:
Can only have one anonymous define call per script file.
解决方案: 用一个script
标签占位,直接修改其src来实现 socket.io
的加载。