我正在编写一个后端,我需要使用通过标准输入传递的文本执行某些命令,然后从标准输出读取结果。
Node.ChildProcess
模块提供了此类实用程序,但我没有看到任何方法可以等到子进程退出。这很奇怪,因为如果应用程序尚未在其中写入任何内容,则从标准输出读取数据是没有意义的。
就一个最小的例子而言,我正在使用
cat
。 cat
从标准输入读取文本并写入标准输出。
module Main where
import Prelude
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Console (log)
import Node.ChildProcess as Proc
import Node.Encoding (Encoding(UTF8))
import Node.Stream as Stream
main :: Effect Unit
main = do
child :: Proc.ChildProcess <- Proc.spawn "cat" []
let
stdin' :: Stream.Writable ()
stdin' = Proc.stdin child
_ <- Stream.writeString stdin' UTF8 "hello"
_ <- Stream.end stdin'
-- wait for child ?? How?
let
stdout' :: Stream.Readable ()
stdout' = Proc.stdout child
output :: Maybe String <- Stream.readString stdout' UTF8
case output of
Just s -> log s
_ -> log "nothing"
我希望打印
hello
,因为这就是 cat
写入其标准输出的内容。相反,毫不奇怪,我得到“什么也没有”,因为当执行 Stream.readString
时,cat
还没有向标准输出写入任何内容。
如何等待
cat
退出?
当进程退出时,Node 将触发一个
"exit"
事件,该事件映射到 PureScript as exitH
,并且您可以使用 on_
中的 Node.EventEmitter
函数附加一个侦听器。
由于您的程序都是同步的(在
Effect
中运行),因此您应该将子进程退出后发生的所有事情放入 "exit"
事件处理程序中:
main :: Effect Unit
main = do
child :: Proc.ChildProcess <- Proc.spawn "cat" []
let
stdin' :: Stream.Writable ()
stdin' = Proc.stdin child
_ <- Stream.writeString stdin' UTF8 "hello"
_ <- Stream.end stdin'
child # on_ Proc.exitH \_ -> do
let
stdout' :: Stream.Readable ()
stdout' = Proc.stdout child
output :: Maybe String <- Stream.readString stdout' UTF8
case output of
Just s -> log s
_ -> log "nothing"