如何使用 Node.js 开发交互式命令行应用程序

来源:互联网 发布:哈飞里程表 算法 编辑:程序博客网 时间:2024/05/16 01:40

本文标签:Node.js交互式命令行应用程序

在过去五年中,Node.js 使软件开发统一起来。您可以用 Node.js 做任何你能想到的事情,无论是前端开发,服务器端脚本,跨平台桌面应用程序,跨平台移动应用程序,物联网等。编写命令行工具也比以往任何时候都更容易,因为Node.js —— 不仅是一个命令行工具,它还具有交互式,易用和开发耗时少等特点。

如果您是前端开发人员,那么您肯定听说过或者用过 Gulp , Angular CLI ,Cordova ,Yeoman 等。你有没有想过他们如何工作的?例如,就Angular CLI来说,通过运行诸如ng new <project-name>命令就能创建一个具有基本配置的Angular新项目。而 Yeoman 等工具也要求运行时输入最后帮助您自定义项目的配置。Yeoman中的一些生成器可 帮助你将项目发布到生产环境中 。这就是我们今天要学习的。

在 SMASHINGMAG 上的相关阅读:

  • A Detailed Introduction To Webpack (详细介绍 Webpack)

  • An Introduction To Node.js And MongoDB (介绍 Node.js 和 MongoDB)

  • Server-Side Rendering With React, Node And Express (使用 React、Node 和 Express 进行服务端渲染)

  • Useful Node.js Tools, Tutorials And Resources (Node.js 工具、教程及资源)

我们会在本教程中开发一个命令行程序,它会接收一个包含客户信息的 CSV 文件,然后使用 SendGrid API 向这些客户发送电子邮件。下面是这篇教程的目录:

  1. “Hello, World”

  2. 处理命令行参数

  3. 运行时用户输入

  4. 异步网络通信

  5. 美化 CLI 输出

  6. 使其成为 shell 命令

  7. JavaScript 之外

“Hello, World”

本教程假设你已经安装了 Node.js。如果你还没有安装,请先 安装 。Node.js 带有一个叫  npm 的包管理器。使用 npm,你可以安装很多开源的包。在 npm 的官方网站 可以看到这些包的完整列表。我们这个项目中会用到许多开源模块(稍后会用到更多)。现在先使用 npm 创建一个 Node.js 项目。

$ npm initname: broadcastversion: 0.0.1description: CLI utility to broadcast emailsentry point: broadcast.js

这里我创建了一个名为 broadcast 的目录,并在其中运行了 npm init 命令。然后提供了一些项目的基本信息,比如名称(name)、说明(description)、版本(version)和入口(entry point)。入口是指执行脚本时最开始执行的 JavaScript 文件。默认情况下,Node.js 把 index.js 作为入口;不过在这个示例中,我们把入口改为 broadcast.js 了。运行 npm init 命令的时候,你会看到更多选项,比如 Git 库、许可证和作者。你可以输入某些值,也可以留空不填。

成功执行 npm init 之后你会发现当前目录下出现了一个 package.json 文件。这是我们的配置文件。现在,它保存着我们创建项目的时候输入的信息。如果你想更详细的了解 package.json,可以看看npm 的文档 。

现在我们已经建立了项目,接下来开始写 “Hello World” 程序。先在项目中创建 broadcast.js 文件,它会是你的主文件。在文件中输入如下这段代码:

console.log('hello world');

运行这段代码。

$ node broadcasthello world

你可以看到控制台输出 “hello world”。你可以通过 node broadcast.js 来运行,也可以通过 node broadcast 来运行。Node.js 能够识别这两种方式。

在 package.json 的文档中,提到了一个名为 dependencies 的选项。在这个选项中你可以申明想用于本项目的所有第三方模块以及它们的版本号。我曾提到我们会在开发这个工具的过程中使用很多第三方开源模块,因此,我们的 package.json 看起来是这样的:

{  "name": "broadcast",  "version": "0.0.1",  "description": "CLI utility to broadcast emails",  "main": "broadcast.js",  "license": "MIT",  "dependencies": {    "async": "^2.1.4",    "chalk": "^1.1.3",    "commander": "^2.9.0",    "csv": "^1.1.0",    "inquirer": "^2.0.0",    "sendgrid": "^4.7.1"  }}

我们会使用 Async 、 Chalk 、 Commander 、 CSV 、 Inquirer.js 和  SendGrid ,在教程进行的过程中,我们会逐步讲解这些模块的用法。

处理命令行参数

获取命令行参数并不困难,只需要使用 process.argv 就可以了。但解析这些参数的值和选项可是件累人的活。所以,与其重复发明轮子,不如直接用  Commander 模块。Commander 是个开源的 Node.js 模块,用于帮助我们写可交互的命令行工具。它带来了很多用于解析命令行选项的特性,而且还支持 git 风格的子命令。我最喜欢的 Commander 特性是自动生成到屏幕的帮助信息。你不需要写多余的代码 —— 只需要解析 --help 或 -h 选项就可以了。你在定义各种命令行选项的时候,它会自动生成 --help 帮助信息。让我们用一下看看:

$ npm install commander --save

这行命令会在你的 Node.js 项目中安装 Commander 模块。在 npm 命令中使用 --save 选项会自动将 Commander 包含在项目的依赖项(dependencies)中,上面曾提到它在 package.json 中定义。在我们这个示例中,所有依赖项都已经申明了,所以我们不需要运行这个命令。

var program = require('commander');program  .version('0.0.1')  .option('-l, --list [list]', 'list of customers in CSV file')  .parse(process.argv)console.log(program.list);

可以看到,处理命令行参数很简单。我们已经完成了对 --list 选项的定义。现在只要是在 --list 选项之后的值都会保存在括号里申明的变量中——在本例中,叫 list。你可以通过 program 命令来访问它,这个 program 是 Commander 的实例。目前这个程序只是通过 --list 来接收一个文件路径然后打印到控制台。

$ node broadcast --list input/employees.csvinput/employees.csv

你一定也注意到了我们调用方法链中的一个方法,version。如果我们在运行命令的时候使用 --version 或 -V 作为参数,就会打印出作为参数转入到这个方法的值。

$ node broadcast --version0.0.1

同样,如果运行命令的时候给出 --help 选项,它会打印出所有定义好的选项和子命令。本例中的输出是这样的:

$ node broadcast --help  Usage: broadcast [options]  Options:    -h, --help                 output usage information    -V, --version              output the version number    -l, --list <list>          list of customers in CSV file

现在我们已经可以从命令行参数中接收到文件路径,接下来开始使用 CSV 模块读取 CSV 文件。CSV 模块提供处理 CSV 文件的全面解决方案。从创建 CSV 文件到进行解析,都可以用这个模块来实现。

因为我们打算使用 SendGrid API 来发送电子邮件,所以用下面这个文档来作为 CSV 文件的示例。我们会使用 CSV 模块来读取数据,并显示出相应行中的姓名和电子邮件地址。

First nameLast nameEmailDwightSchrutedwight.schrute@dundermifflin.comJimHalpertjim.halpert@dundermifflin.comPamBeeslypam.beesly@dundermifflin.comRyanHowardryan.howard@dundermifflin.comStanleyHudsonstanley.hudson@dundermifflin.com

现在让我们来写一段程序,从 CSV 文件中读取数据并打印到控制台。

const program = require('commander');const csv = require('csv');const fs = require('fs');program  .version('0.0.1')  .option('-l, --list [list]', 'List of customers in CSV')  .parse(process.argv)let parse = csv.parse;let stream = fs.createReadStream(program.list)    .pipe(parse({ delimiter : ',' }));stream  .on('data', function (data) {    let firstname = data[0];    let lastname = data[1];    let email = data[2];    console.log(firstname, lastname, email);  });

我们可以使用原生的 文件系统(File System) 模块读取从命令行参数获取的文件。文件系统模块中预定义了事件,其中 data 事件会在读取到一块数据时触发。CSV 模块提供的 parse 方法能将 CSV 文件拆分行,并多次触发 data 事件。每个 data 事件都会发送一个数组,包含每一列的数据。那么,在本例中会按下面的格式打印数据:

$ node broadcast --list input/employees.csvDwight Schrute dwight.schrute@dundermifflin.comJim Halpert jim.halpert@dundermifflin.comPam Beesly pam.beesly@dundermifflin.comRyan Howard ryan.howard@dundermifflin.comStanley Hudson stanley.hudson@dundermifflin.com

运行时用户输入

我们已经知道如何接收命令行参数并解析它们。但是如果想在运行时获取输入该怎么办呢? Inquirer.js 模块能让我们接收不同类型的输入,包括纯文本、密码和可多选项的列表等。

在这个示例中,我们会在运行时接收用户输入的电子邮件地址和姓名。

…let questions = [  {    type : "input",    name : "sender.email",    message : "Sender's email address - "  },  {    type : "input",    name : "sender.name",    message : "Sender's name - "  },  {    type : "input",    name : "subject",    message : "Subject - "  }];let contactList = [];let parse = csv.parse;let stream = fs.createReadStream(program.list)    .pipe(parse({ delimiter : "," }));stream  .on("error", function (err) {    return console.error(err.message);  })  .on("data", function (data) {    let name = data[0] + " " + data[1];    let email = data[2];    contactList.push({ name : name, email : email });  })  .on("end", function () {    inquirer.prompt(questions).then(function (answers) {      console.log(answers);    });  });

首先,注意上例中我们创建了一个名为 contactList 的数组,我们用它保存来自 CSV 文件的数据。

Inquirer.js 有一个叫做 prompt 的方法,它的参数是一组我们想在运行时提出的问题。在本例中就是我们想知道的发送者的姓名、电子邮件地址和电子邮件的主题。我们创建了一个叫 questions 的数组,用来保存这些问题。这个数组的元素是一个包含像类型(type)这类属性的对象,类型用于标识输入的是密码还是列表,或者其它。你可以在官方文档 看到完整的类型列表。这里的  name 保存了用户输入所需要保存的信息的名称。  prompt 方法返回一个 Promise 对象,根据成功或者失败会调用不同的回调函数,当然这会在用户回答完所有问题之后进行。用户的回答通过 then 回调的参数  answers 来访问。执行上述代码会得到如下结果:

$ node broadcast -l input/employees.csv? Sender's email address -  michael.scott@dundermifflin.com? Sender's name -  Micheal Scott? Subject - Greetings from Dunder Mifflin{ sender:   { email: 'michael.scott@dundermifflin.com',     name: 'Michael Scott' },  subject: 'Greetings from Dunder Mifflin' }

写在最后:FOR Freedom 看看外边的世界,以及IT这一行,少不了去Google查资料,最后,安利一个加速器代理。一枝红杏 加速器,去Google查资料是绝对首选,连接速度快,使用也方便。我买的是99¥一年的,通过这个链接(http://whosmall.com/go/yzhx)注册后输上优惠码wh80,终身85折 ,平摊下来,每月才7块钱,特实惠。

本文标签:Node.js交互式命令行应用程序GoogleChromeChrome扩展工具ChromeDevTools

转自 SUN'S BLOG - 专注互联网知识,分享互联网精神!

原文地址: 如何使用 Node.js 开发交互式命令行应用程序

相关阅读:分享一些对开发者最有用的、用户友好和功能丰富的Google Chrome扩展工具

相关阅读:分享一些实际Android开发过程中很多相见恨晚的工具或网站

相关阅读:我是 G 粉,一直关注 Google,最近 Google 有一些小动作,可能很多人不太了解

相关阅读:机器学习引领认知领域的技术创新,那么SaaS行业会被机器学习如何改变?

相关阅读:VPS 教程系列:Dnsmasq + DNSCrypt + SNI Proxy 顺畅访问 Google 配置教程

相关阅读: 对程序员有用:2017最新能上Google的hosts文件下载及总结网友遇到的各种hosts问题解决方法及配置详解

相关BLOG:SUN’S BLOG- 专注互联网知识,分享互联网精神!去看看:www.whosmall.com

原文地址:http://whosmall.com/?post=372

0 0
原创粉丝点击