我想使用Node在特定的时间以特定的顺序启动两个子进程,在它们流化时控制台记录它们的stdout
,偶尔在两者之间切换。
`Proc 1 log # 1`
`Proc 1 log # 2`
`Proc 1 log # 3`
`Proc 1 log # 4`
`Proc 2 log # 1`
`Proc 2 log # 2`
`Proc 2 log # 3`
`Proc 2 log # 4`
`Proc 1 log # 9`
`Proc 1 log # 10`
`Proc 1 log # 11`
`Proc 1 log # 12`
`Proc 1 log # 13`
`Proc 1 log # 14`
`Proc 1 log # 15`
`All procs have finished!`
当然,这很容易做到。 紧急地。但这也真的很丑且有状态,只是敦促。因此,我试图纯粹地做到这一点,并使用了来自于民间传说的Task
monad(即旧的)来进行计算,用手像一个笨拙的对象一样通过有状态对象:
// main _ :: Task error {childProcs}
const main = startProc1({})
.chain(logUntilProc1IsReady)
.chain(startProc2)
.chain(logUntilProc2IsReady)
.chain(logUntilProc1IsFinished)
更漂亮。如果可以的话,那就更好了!
`Proc 1 log # 1`
`Proc 1 log # 2`
`Proc 1 log # 3`
`Proc 1 log # 4`
`Proc 2 log # 1`
`Proc 1 log # 6` // <-- These should not be logged
`Proc 2 log # 2`
`Proc 1 log # 7`
`Proc 2 log # 3`
`Proc 1 log # 8`
`Proc 2 log # 4`
`Proc 1 log # 9`
`Proc 1 log # 10` // <-- now it's logging twice! :confounded:
`Proc 1 log # 10`
`Proc 2 log # 6`
`Proc 1 log # 11`
`Proc 1 log # 11`
`Proc 2 log # 7`
`Proc 1 log # 12`
`Proc 1 log # 12`
`Proc 2 log # 8`
`Proc 1 log # 13`
`Proc 1 log # 13`
`Proc 2 log # 9`
`Proc 1 log # 14`
`Proc 1 log # 14`
`Proc 2 log # 10`
`All procs have finished!`
这是日志记录功能:
// logStreamUntil :: int -> (a -> bool) -> proc -> string -> Task error State () {childProcs}
const logStreamUntil = curry((predFunc, procName, procObj) =>
new Task ((_, res) => {
const proc = procObj[procName]
const logUntilPred = data =>
predFunc(data)
? (rmAllListeners(proc), res(procObj))
: console.log(data)
proc.stdout.on('data', logUntilPred)
}))
其中的tl; dr:是向我发送一个进程名称和一个对象,该对象将从中抽取实际的子进程,还有一个谓词函数,用于决定控制台日志{{ 1}}的任何子进程。谓词只是在stdout
的字符串中查找特定内容。因此,当谓词函数返回false时,它会控制台记录输出,否则它将停止记录,删除监听器,应该就是这样!
然后是stdout
函数:
rmAllListeners
后者显然是问题所在。侦听器尽管已被命名为命名空间,并且据称已被上述内容淘汰,但它们并未存在。而且我不知道为什么?!?救命!
对于有兴趣看完整本书的人也有一个回购清单:you can find it here。
答案 0 :(得分:2)
您正在从proc
而不是从stdout
移除侦听器。之所以会出现双打,是因为您要将侦听器的第二个副本附加到proc.stdout
上的'data'事件中。
在.stdout
中添加rmAllListeners
可以为我解决此问题:
diff --git a/why-log-twice.js b/why-log-twice.js
index 276d15c..6c15467 100644
--- a/why-log-twice.js
+++ b/why-log-twice.js
@@ -7,7 +7,7 @@ const PROC_ONE_PATH = `node child-proc "Proc 1 log # "`
const PROC_TWO_PATH = `node child-proc "Proc 2 log # "`
// rmAllListeners :: childProc -> childProc
-const rmAllListeners = proc => (proc.removeAllListeners(), proc.stdout.unref())
+const rmAllListeners = proc => (proc.stdout.removeAllListeners(), proc.stdout.unref())
// procIsReady :: string -> bool
const procIsReady = str => str.includes('5')