我正在封装一个我用NodeJS制作的可执行文件。可执行文件可以保存字符串以供可执行文件中的其他进程使用。每次可执行文件“保存”一个字符串时,它都会通过stdout将指针发送回服务器。 NodeJS服务器通过将字符串发送到可执行文件的stdin来保存字符串。所有回调都在同一时间执行,但为什么?
本来我正在写这样的代码:
CLRProcess.stdout.once('data',function(strptr){
CLRProcess.stdout.once('data', function(str){
console.log(str.toString())
})
CLRProcess.stdin.write("StringReturn " + strptr.toString())
})
CLRProcess.stdin.write("StringInject __CrLf__ Mary had a__CrLf__little lamb.")
上面的代码注入的字符串
Mary had a
little lamb.
接收的指针串,然后在下一步骤中请求字符串,由将指针发送回主应用程序。
为了使编码算法更容易,我想这样的系统:
strPtr = Exec("StringInject __CrLf__ Mary had a__CrLf__little lamb.")
str = Exec("StringReturn " + strPtr)
// do stuff with str
这是我做的代码:我打算这样做以下
class Pointer {
constructor(){
this.value = undefined
this.type = "ptr"
}
}
class CLR_Events extends Array {
constructor(CLR){
super()
this.CLR = CLR
}
runAll(){
if(this.length>0){
//Contribution by le_m: https://stackoverflow.com/a/44447739/6302131. See Contrib#1
this.shift().run(this.runAll.bind(this))
}
}
new(cmd,args,ret){
var requireRun = !(this.length>0) //If events array is initially empty, a run is required
var e = new CLR_Event(cmd,args,ret,this.CLR)
this.push(e)
if(requireRun){
this.runAll()
}
}
}
class CLR_Event {
constructor(cmd,args,ret,CLR){
this.command = cmd;
this.args = args
this.CLR = CLR
this.proc = CLR.CLRProcess;
this.ptr = ret
}
run(callback){
//Implementing event to execute callback after some other events have been created.
if(this.command == "Finally"){
this.args[0]()
console.log("Running Finally")
return callback(null)
}
//Implementation for all CLR events.
var thisEvent = this
this.proc.stdout.once('data',function(data){
this.read()
data = JSON.parse(data.toString())
thisEvent.ptr.value = data
callback(data);
})
this.proc.stdin.write(this.command + " " + this._getArgValues(this.args).join(" ") + "\n");
}
_getArgValues(args){
var newArgs = []
this.args.forEach(
function(arg){
if(arg.type=='ptr'){
if(typeof arg.value == "object"){
newArgs.push(JSON.stringify(arg.value))
} else {
newArgs.push(arg.value)
}
} else if(typeof arg == "object"){
newArgs.push(JSON.stringify(arg))
} else {
newArgs.push(arg)
}
}
)
return newArgs
}
}
var CLR = {}
CLR.CLRProcess = require('child_process').spawn('DynaCLR.exe')
CLR.CLRProcess.stdout.once('data',function(data){
if(data!="Ready for input."){
CLR.CLRProcess.kill()
CLR = undefined
throw new Error("Cannot create CLR process")
} else {
console.log('CLR is ready for input...')
}
})
CLR.Events = new CLR_Events(CLR)
//UDFs
CLR.StringInject = function(str,CrLf="__CLR-CrLf__"){
var ptr = new Pointer
this.Events.new("StringInject",[CrLf,str.replace(/\n/g,CrLf)],ptr) //Note CLR.exe requires arguments to be the other way round -- easier command line passing
return ptr
}
CLR.StringReturn = function(ptr){
var sRet = new Pointer
this.Events.new("StringReturn",[ptr],sRet)
return sRet
}
CLR.Finally = function(callback){
this.Events.new("Finally",[callback])
}
:
- 函数
StringInject
,StringReturn
和Finally
创建事件并追加它们到Events
阵列。 Events
对象的runAll()
函数从数组中移除第一个“事件”并运行数组的run()
函数,并将其自身作为回调函数传递。- 运行函数写入可执行文件的stdin,等待stdout中的响应,将数据追加到传入的指针中,然后执行传递给它的函数
runAll()
。
这是我不明白...当执行多个字符串注射:
S_ptr_1 = CLR.StringInject("Hello world!")
S_ptr_2 = CLR.StringInject("Hello world!__CLR-CrLf__My name is Sancarn!")
S_ptr_3 = CLR.StringInject("Mary had a little lamb;And it's name was Doug!",";")
我得到以下数据:
S_ptr_1 = {value:123,type:'ptr'}
S_ptr_2 = {value:123,type:'ptr'}
S_ptr_3 = {value:123,type:'ptr'}
凡作为数据应该是:
S_ptr_1 = {value:1,type:'ptr'}
S_ptr_2 = {value:2,type:'ptr'}
S_ptr_3 = {value:3,type:'ptr'}
我可以认为这会发生的唯一情况是if发生以下情况:
CLRProcess.stdin.write("StringInject Val1")
CLRProcess.stdin.write("StringInject Val2")
CLRProcess.stdin.write("StringInject Val3")
CLRProcess.stdout.once('data') ==> S_ptr_1
CLRProcess.stdout.once('data') ==> S_ptr_2
CLRProcess.stdout.once('data') ==> S_ptr_3
但是为什么?我是否忽略了某些东西,或者这种算法存在根本性错误?
听起来你俯瞰事实'write'是异步的。另外,'新的指针'不会创建一个对象。您需要调用构造函数:'new Pointer()' – slebetman
您只有一个CLR对象,因此只有一个DynaCLR.exe,因此每个stdin和stdout流只有一个。如果您要为每个呼叫创建一个新的DynaCLR,您可能会获得更多成功。 – GregHNZ
@GregHNZ是的。要求只有1个标准输入/标准输出流。一切都应该由同一个DynaCLR可执行文件保存,因为我将使用它来编译VB和C#源代码。将它们存储在多个不同的进程中将不会允许这种可能性(不存储物理文件,这对我来说不可能)。使用stdin/out只是IPC的一种手段。 – Sancarn