/func-log

Why does this console log twice?

Primary LanguageJavaScript

❓ Why does this log twice?

📃 Instructions

1. Clone repo & submodules:

❍ git clone https://github.com/gskapka/func-log.git

2. Switch into directory:

❍ cd func-log

3. Install dependencies:

❍ npm install

4. Run tests:

❍ node why-log-twice

 


 

💥 The Issue:

Expected output:

`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!`

Actual output:

`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!`

 

😭 What I'm trying to do.

Obviously to have javascript fire up two child processes and then follow their stdout's for a time, logging as they streams, switching between them at will is super easy to do. Imperatively. It's also really ugly, & stateful and just urgh. So I'm trying to do it purely, and have built up the computation using the Task monad from folktale (the old one, that is), threading through a stateful object by hand like a chump:

//    main _ :: Task error {childProcs}
const main = startProc1({})
  .chain(logUntilProc1IsReady)
  .chain(startProc2)
  .chain(logUntilProc2IsReady)
  .chain(logUntilProc1IsFinished)

 

Much prettier. It would be much better too, if it worked - help! 😵

 

Here is the logging function:

 

//    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)
}))

 

And here is the rmAllListeners function:

 

//    rmAllListeners :: childProc -> childProc           
const rmAllListeners = proc => (proc.removeAllListeners(), proc.stdout.unref())

 

Which latter is clearly the issue. Listeners, despite being namespaced and supposedly obliterated by the above, are not being. Why?

 

 


 

📋 To Do List

🔲 Make it.

🔲 Make it work.

✅ Fail at figuring out why it doesn't work.

🔲 Ask other people to make it work.