使用 JavaScript 实现交互命令行| 青训营

79 阅读2分钟

通常,命令行程序会通过读取命令行的参数来更改程序的运行方式。但有的时候,我们希望一步一步引导用户完成参数的输入,而非甩给用户一串需要花时间理解的帮助信息。

在 Windows 中,PowerShell 的许多命令都能够对用户没有指定的参数进行询问,而传统的命令行程序则只会提示“命令语法不正确”或者显示帮助信息。对于一个对命令较为陌生的用户而言,前者显然更容易令人接受。

image.png

image.png

那么,JavaScript(或者具体一些,Node.js)该如何实现类似的效果呢?

通过查找资料,我们得知可以对 process.stdin 设置事件监听。当标准输入流中产生数据时,程序就会对事件作出响应。

process.stdin.on("data", data => {
    console.log(data)
})

运行效果如图,当我们在命令行中输入字符并按下回车时,程序确实可以接收到输入的数据,并打印 data 的值。

image.png

看来,我们离实现交互式命令行又近了一步。那如果要通过这种方式实现一个类似 curl 的命令行网络请求工具,可以通过参数提供网址,如果没有提供就询问用户,那应该怎么做呢?

下方代码就是这个功能的一种简单实现。首先,程序会检查参数是否有值。由于参数的第一项在这里总是 node,第二项总是这段 JavaScript 代码所在的位置,所以我们检查参数的第三项,也就是下标为 2 的这一项是否有值。如果有,那就将其作为 URL 传递给 request() 函数。如果没有,则通过交互的方式要求用户输入 URL,用户回车后再将接收到的 URL 传递给 request() 函数。

function input(data) {
    process.stdin.off("data", input)
    request(data.toString())
}
function request(url) {
    return fetch(url).then(res => { res.text().then(text => { console.log(text);process.exit() }) })
}
if (process.argv[2]) {
    request(process.argv[2])
} else {
    console.log('URL: ')
    process.stdin.on("data", input)
}

运行这段代码,并从命令行提供 URL 参数,可以看到程序直接访问了指定的网站,并传回了网页的内容。

image.png

再次运行这段代码,但不提供 URL 参数,程序便会询问用户希望访问的 URL,然后根据用户的输入进行访问。

image.png

至此,我们成功使用 JavaScript 实现了交互式命令行。当然,已经有前人给我们提供了诸如 readline 的优秀依赖库,我们可以通过引入依赖的方式更方便地从标准输入流接收数据,而无需自行处理监听事件。