我正在封裝一個我用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