node.js启动应用命令_如何使用Node.js构建命令行应用程序

news/2024/7/5 6:12:38

node.js启动应用命令

As a developer, chances are you spend most of your time in your terminal, typing in commands to help you get around some tasks.

作为开发人员,您很可能会花费大部分时间在终端上,输入命​​令来帮助您解决一些任务。

Some of these commands come built into your Operating System, while some of them you install through some third party helper such as npm, or brew, or even downloading a binary and adding it to your $PATH.

其中一些命令内置在您的操作系统中,而另一些命令则通过第三方帮助程序(例如npm或brew)安装,甚至下载二进制文件并将其添加到$PATH

A good example of commonly used applications include npm, eslint, typescript, and project generators, such as Angular CLI, Vue CLI or Create React App.

常用应用程序的一个很好的例子包括npm,eslint,打字稿和项目生成器,例如Angular CLI , Vue CLI或Create React App 。

In this tutorial you’ll build two small CLI applications in Node.js:

在本教程中,您将在Node.js中构建两个小型CLI应用程序:

  1. Quote Of The Day tool that retrieves quotes of the day from https://quotes.rest/qod.

    每日报价工具,可从https://quotes.rest/qod检索当天的报价。

  2. A To-Do List app that uses JSON to save data.

    使用JSON保存数据的待办事项列表应用程序。

先决条件 (Prerequisites)

To complete this tutorial, you will need:

要完成本教程,您将需要:

  • A local development environment for Node.js. Follow How to Install Node.js and Create a Local Development Environment

    Node.js的本地开发环境。 遵循如何安装Node.js和创建本地开发环境

步骤1 –了解Shebang (Step 1 – Understanding the Shebang)

Whenever you look at any scripting file, you’ll see characters like these in the beginning of the file:

每当您查看任何脚本文件时,都将在文件开头看到以下字符:


   
file.sh
#!/usr/bin/env sh

Or this:

或这个:


   
file.py
#!/usr/bin/env python -c

They serve as a way for your operating system program loader to locate and use toe parse the correct interpreter for your executable file. This only works in Unix Systems though.

它们是您的操作系统程序加载程序找到并使用它为可执行文件解析正确的解释器的一种方式。 不过,这仅适用于Unix系统。

From Wikipedia:

从维基百科 :

In computing, a shebang is the character sequence consisting of the characters number sign and exclamation mark (#!) at the beginning of a script.

在计算中,shebang是由脚本开头的字符数字符号和感叹号(#!)组成的字符序列。

NodeJS has its own supported shebang characters.

NodeJS具有自己支持的shebang字符。

Create a new file in your editor called logger.js:

在名为logger.js的编辑器中创建一个新文件:

  • nano logger.js

    纳米logger.js

Add the following code:

添加以下代码:

#!/usr/bin/env node

console.log("I am a logger")

The first line tells the program loader to parse this file with NodeJS. The second line prints text to the screen.

第一行告诉程序加载器使用NodeJS解析此文件。 第二行将文本打印到屏幕上。

You can try and run the file by typing this in your terminal. You’ll get a permission denied for execution.

您可以通过在终端中键入此文件来尝试运行该文件。 您将获得拒绝执行的权限。

  • ./logger

    ./logger

   
Output
zsh: permission denied: ./logger

You need to give the file execution permissions. You can do that with.

您需要授予文件执行权限。 您可以这样做。

  • chmod +x logger

    chmod + x记录器
  • ./logger

    ./logger

This time you’ll see the output.

这次您将看到输出。


   
Output
I am a logger

You could have run this program with node logger, but adding the shebang and making the program executable own command lets you avoid typing node to run it.

您可以使用node logger运行该程序,但是添加shebang并使该程序可执行自己的命令可以避免键入node来运行它。

创建每日报价应用程序 (Creating the Quote of the Day App)

Let’s create a directory and call it qod. And inside, instantiate a NodeJs app.

让我们创建一个目录并将其命名为qod 。 在内部,实例化NodeJs应用程序。

  • mkdir qod

    mkdir qod
  • cd qod

    cd qod
  • npm init -y

    npm初始化-y

Next, we know we need to make requests to the quotes server, so we could use existing libraries to do just this. We’ll use axios

接下来,我们知道我们需要向报价服务器发出请求,因此我们可以使用现有的库来做到这一点。 我们将使用axios

npm install --save axios

We’ll also add a chalk, a library to help us print color in the terminal.

我们还将添加一个粉笔 ,一个库来帮助我们在终端上打印颜色。

npm install --save chalk

We then write the logic needed to retrieve these quotes.

然后,我们编写检索这些引号所需的逻辑。

Create a new file called qod:

创建一个名为qod的新文件:

  • nano qod

    纳米级

Add the following code to the qod file to specify the shebang, load the libraries, and store the API URL:

将以下代码添加到qod文件中以指定shebang,加载库并存储API URL:

qod
od
#!/usr/bin/env node

const axios = require('axios');
const chalk = require('chalk');

const url = "https://quotes.rest/qod";

Next, add this code to make a GET request to the API:

接下来,添加以下代码以向API发出GET请求:

qod
od
// make a get request to the urlaxios({
  method: 'get',
  url: url,
  headers: { 'Accept': 'application/json' }, // this api needs this header set for the request
}).then(res => {
  const quote = res.data.contents.quotes[0].quote
  const author = res.data.contents.quotes[0].author
  const log = chalk.green(`${quote} - ${author}`) // we use chalk to set the color green on successful response
  console.log(log)
}).catch(err => {
  const log = chalk.red(err) // we set the color red here for errors.
  console.log(log)
})

Save the file.

保存文件。

Change the file permissions so the file is executable:

更改文件权限,以便文件可执行:

  • chmod +x qod

    chmod + x qod

Then run the application:

然后运行该应用程序:

./qod

You’ll see a quote:

您会看到一个报价:


   
Output
The best way to not feel hopeless is to get up and do something. Don’t wait for good things to happen to you. If you go out and make some good things happen, you will fill the world with hope, you will fill yourself with hope. - Barack Obama

This example shows you can use external libraries in your CLI applications.

本示例说明您可以在CLI应用程序中使用外部库。

Now let’s create a CLI program that saves data.

现在,让我们创建一个保存数据的CLI程序。

创建待办事项清单 (Creating a To-Do List)

This will be a bit more complex, as it will involve data storage, and retrieval. Here’s what we’re trying to achieve.

这将更加复杂,因为它将涉及数据存储和检索。 这是我们正在努力实现的目标。

  1. We need to have a command called todo

    我们需要有一个名为todo的命令

  2. The command will take in four arguments. new, get, complete, and help.

    该命令将接受四个参数。 newgetcompletehelp

So the available commands will be

所以可用的命令将是

./todo new // create a new todo
./todo get // get a list of all your todos
./todo complete // complete a todo item.
./todo help // print the help text

Create a directory called todo, and instantiate a Node.js app:

创建一个名为todo的目录,并实例化Node.js应用程序:

  • mkdir todo

    麦克迪尔·托多
  • cd todo

    cd待办事项
  • npm install -y

    npm install -y

Next, install chalk again, so that you can log with colors.

接下来,再次安装粉笔 ,以便您可以记录颜色。

npm install --save chalk

The first thing we’re going to do is make sure we have these commands available. To get the commands working, we’ll use NodeJs’ process/argv which returns a string array of command line arguments The process.argv property returns an array containing the command line arguments passed when the Node.js process was launched.

我们要做的第一件事是确保我们有这些命令可用。 要获得命令的工作中,我们将使用的NodeJS' 进程/ argv的返回的命令行参数的字符串数组的process.argv属性返回时Node.js的过程中推出包含命令行参数的数组传递。

Create the file todo:

创建文件todo

  • nano todo

    纳米待办事项

Add this to the todo file.

将此添加到待办事项文件。

todo
去做
#!/usr/bin/env node

console.log(process.argv)

Give the file executable permissions, and then run it with a new command.

授予文件可执行权限,然后使用新命令运行它。

  • chmod +x ./todo

    chmod + x ./待办事项
  • ./todo new

    ./todo新

You’re going to get this output:

您将获得以下输出:


   
Output
[ '/Users/sammy/.nvm/versions/node/v8.11.2/bin/node', '/Users/sammy/Dev/scotch/todo/todo', 'new' ]

Notice that the first two strings in the array are the interpreter and the file full path to the program. The rest of the array contains the arguments passed; in this case it’s new.

请注意,数组中的前两个字符串是解释器和程序的文件完整路径。 数组的其余部分包含传递的参数。 在这种情况下,它是new

To be safe, let’s restrict these, so that we can only accept the correct number of arguments, which is one, and they can only be new, get and complete.

为了安全起见,我们限制它们,以便我们只能接受正确数量的参数,即一个,并且它们只能是newgetcomplete

Modify the todo file so it looks like the following:

修改todo文件,使其如下所示:

todo
去做
#!/usr/bin/env node

const chalk = require('chalk')
const args = process.argv

// usage represents the help guide
const usage = function() {
  const usageText = `
  todo helps you manage you todo tasks.

  usage:
    todo <command>

    commands can be:

    new:      used to create a new todo
    get:      used to retrieve your todos
    complete: used to mark a todo as complete
    help:     used to print the usage guide
  `

  console.log(usageText)
}

// used to log errors to the console in red color
function errorLog(error) {
  const eLog = chalk.red(error)
  console.log(eLog)
}

// we make sure the length of the arguments is exactly three
if (args.length > 3) {
  errorLog(`only one argument can be accepted`)
  usage()
}

We’ve first assigned the command line arguments to a variable, and then we check at the bottom that the length is not greater than three.

我们首先将命令行参数分配给一个变量,然后在底部检查该长度不大于3。

We’ve also added a usage string, that will print what the command line app expects. Run the app with wrong parameters like below.

我们还添加了一个usage字符串,该字符串将打印命令行应用程序期望的内容。 使用错误的参数运行应用程序,如下所示。

  • ./todo new app

    ./todo新应用

   
Output
only one argument can be accepted todo helps you manage you todo tasks. usage: todo <command> commands can be: new: used to create a new todo get: used to retrieve your todos complete: used to mark a todo as complete help: used to print the usage guide

If you run it with one parameter, it will not print anything, which means the code passes.

如果使用一个参数运行它,它将不会打印任何内容,这意味着代码可以通过。

Next, we need to make sure only the four commands are expected, and everything else will be printed as invalid.

接下来,我们需要确保仅期望使用这四个命令,而其他所有命令都将被打印为无效命令。

Add a list of the commands at the top of the file:

在文件顶部添加命令列表:

todo
去做
const commands = ['new', 'get', 'complete', 'help']

And then check with the passed in command after we’ve checked the length:

在检查了长度之后,请使用传递的命令进行检查:

todo
去做
...
if (commands.indexOf(args[2]) == -1) {
  errorLog('invalid command passed')
  usage()
}

Now, if we run the app with an invalid command, we get this.

现在,如果使用无效命令运行该应用程序,则会得到此信息。

  • ./todo ne

    ./todo ne

   
Output
invalid command passed todo helps you manage you todo tasks. usage: todo <command> commands can be: new: used to create a new todo get: used to retrieve your todos complete: used to mark a todo as complete help: used to print the usage guide

Now let’s implement the help command by calling the usage function. Let’s add this to the todo file:

现在,让我们通过调用usage函数来实现help命令。 让我们将其添加到待办事项文件中:

todo
去做
//...
switch(args[2]) {
  case 'help':
    usage()
    break
  case 'new':
    break
  case 'get':
    break
  case 'complete':
    break
  default:
    errorLog('invalid command passed')
    usage()
}
//...

We have a switch statement which will call functions based on what command has been called. If you look closely, you’ll notice the help case just calls the usage function.

我们有一个switch语句,它将根据所调用的命令来调用函数。 如果仔细观察,您会发现help案例只是调用了用法功能。

The new command will create a new todo item and save it in a json file. The library we will use is lowdb. We could easily write functions to read and write to a json file, if we wanted to.

new命令将创建一个新的待办事项并将其保存在json文件中。 我们将使用的库是lowdb 。 如果愿意,我们可以轻松编写函数以读取和写入json文件。

Install lowdb

安装lowdb

  • npm install --save lowdb

    npm install-保存lowdb

Let’s add [readline](https://nodejs.org/api/readline.html) and lowdb dependencies, to help us with storing data. The lowdb code is standard from their github page.

让我们添加[readline](https://nodejs.org/api/readline.html)lowdb依赖项,以帮助我们存储数据。 lowdb代码是其github页面上的标准代码。

todo
去做
//...
const rl = require('readline');

const low = require('lowdb')
const FileSync = require('lowdb/adapters/FileSync')

const adapter = new FileSync('db.json')
const db = low(adapter)

// Set some defaults (required if your JSON file is empty)
db.defaults({ todos: []}).write()
//...

Next, we’ll add a function to prompt the user to input data.

接下来,我们将添加一个功能来提示用户输入数据。

todo
去做
//...
function prompt(question) {
  const r = rl.createInterface({
    input: process.stdin,
    output: process.stdout,
    terminal: false
  });
  return new Promise((resolve, error) => {
    r.question(question, answer => {
      r.close()
      resolve(answer)
    });
  })
}
//...

Here we are using the readline library to create an interface that will help us prompt a user to and then read the output.

在这里,我们使用readline库创建一个界面,该界面将帮助我们提示用户输入然后读取输出。

Next, we need to add a function that will be called when a user types in the new command:

接下来,我们需要添加一个在用户键入new命令时将调用的函数:

todo
去做
//...
function newTodo() {
  const q = chalk.blue('Type in your todo\n')
  prompt(q).then(todo => {
    console.log(todo)
  })
}
//...

We’re using chalk to get the blue color for the prompt. And then we will log the result.

我们正在使用粉笔来获取提示的蓝色。 然后我们将记录结果。

Lastly, call the function in the new case.

最后,在new情况下调用该函数。

todo
去做
// ...
switch(args[2]) {
  //...
  case 'new':
    newTodo()
    break
    // ...
}
// ...

When you run the app now with the new command, you will be prompted to add in a todo. Type and press enter.

现在,使用新命令运行应用程序时,系统将提示您添加待办事项。 输入并按Enter。

  • ./todo new

    ./todo新

   
Output
Type in your todo This my todo aaaaaaw yeah This my todo aaaaaaw yeah

You should see something similar to this.

您应该会看到类似的内容。

Notice also, that a db.json file has been created in your file system, and it has a todos property.

还要注意,已经在文件系统中创建了一个db.json文件,它具有todos属性。

Next, let’s add in the logic for adding a todo. Modify the newTodo function.

接下来,让我们添加添加待办事项的逻辑。 修改newTodo函数。

todo
去做
//...
function newTodo() {
  const q = chalk.blue('Type in your todo\n')
  prompt(q).then(todo => {
    // add todo
    db.get('todos')
      .push({
      title: todo,
      complete: false
      })
      .write()
  })
}
//...

Run the code again.

再次运行代码。

  • ./todo new

    ./todo新

   
Output
Type in your todo Take a Scotch course

If you look at your db.json, you’ll see the todo added. Add two more, so that we can retrieve them in the next get command. Here’s what the db.json file looks like with more records:

如果查看db.json ,则会看到已添加的待办事项。 再添加两个,以便我们可以在下一个get命令中检索它们。 带有更多记录的db.json文件如下所示:

db.json
db.json
{
  "todos": [
    {
      "title": "Take a Scotch course",
      "complete": false
    },
    {
      "title": "Travel the world",
      "complete": false
    },
    {
      "title": "Rewatch Avengers",
      "complete": false
    }
  ]
}

After creating the new command, you should already have an idea of how to implement the get command.

创建new命令后,您应该已经了解如何实现get命令。

Create a function that will retrieve the todos.

创建一个将检索待办事项的函数。

todo
去做
//...
function getTodos() {
  const todos = db.get('todos').value()
  let index = 1;
  todos.forEach(todo => {
    const todoText = `${index++}. ${todo.title}`
    console.log(todoText)
  })
}
//...

// switch statements
switch(args[2]) {
    //...
    case 'get':
        getTodos()
        break
    //...
}
//....

Run the command again:

再次运行命令:

  • ./todo get

    ./todo获取

Running the app now will give this output:

现在运行该应用程序将给出以下输出:


   
Output
1. Take a Scotch course 2. Travel the world 3. Rewatch Avengers

You can make the color green by using chalk.green.

您可以使用chalk.green绿色来使颜色chalk.green绿色。

Next, add the complete command, which is a little bit complicated.

接下来,添加complete命令,这有点复杂。

You can do it in two ways.

您可以通过两种方式来实现。

  1. Whenever a user types in ./todo complete, we could list all the todos, and the ask them to type in the number/key for the todo to mark as complete.

    每当用户输入./todo complete ,我们都可以列出所有待办事项,并要求他们键入数字/密钥以将待办事项标记为完成。

  2. We can add in another parameter, so that a user can type in ./todo get, and then choose the task to mark as complete with a parameter, such as ./todo complete 1.

    我们可以添加另一个参数,以便用户可以输入./todo get ,然后选择带有参数标记为完成的任务,例如./todo complete 1

Since you learned how to do the first method when you implemented the new command, we’ll look at option 2.

由于您在实现new命令时学习了如何执行第一种方法,因此我们将介绍选项2。

With this option, the command ./todo complete 1, will fail our validity check for the number of commands given. We therefore first need to handle this. Change the function that checks the length of the arguments to this:

使用此选项,命令./todo complete 1将使我们对给定命令数的有效性检查失败。 因此,我们首先需要处理这个问题。 将检查参数长度的函数更改为此:

todo
去做
//...
// we make sure the length of the arguments is exactly three
if (args.length > 3 && args[2] != 'complete') {
  errorLog('only one argument can be accepted')
  usage()
  return
}
///...

This approach uses truth tables, where TRUE && FALSE will equal FALSE, and the code will be skipped when complete is passed.

此方法使用真值表,其中TRUE && FALSE将等于FALSE ,并且在complete传递时将跳过代码。

We’ll then grab the value of the new argument and make the value of todo as completed:

然后,我们将获取新参数的值,并使todo的值完成:

todo
去做
//...
function completeTodo() {
  // check that length
  if (args.length != 4) {
    errorLog("invalid number of arguments passed for complete command")
    return
  }

  let n = Number(args[3])
  // check if the value is a number
  if (isNaN(n)) {
    errorLog("please provide a valid number for complete command")
    return
  }

  // check if correct length of values has been passed
  let todosLength = db.get('todos').value().length
  if (n > todosLength) {
    errorLog("invalid number passed for complete command.")
    return
  }

  // update the todo item marked as complete
  db.set(`todos[${n-1}].complete`, true).write()
}
//...

Also, update the switch statement to include the complete command:

另外,更新switch语句以包含complete命令:

todo
去做
//...
case 'complete':
    completeTodo()
    break
//...

When you run this with ./todo complete 2, you’ll notice your db.json has changed to this, marking the second task as complete:

当使用./todo complete 2运行此./todo complete 2 ,您会注意到db.json已更改为this,将第二项任务标记为完成:

db.json
db.json
{
  "todos": [
    {
      "title": "Take a Scotch course",
      "complete": false
    },
    {
      "title": "Travel the world",
      "complete": true
    },
    {
      "title": "Rewatch Avengers",
      "complete": false
    }
  ]
}

The last thing we need to do is change ./todo get to only show tasks that are done. We’ll use emojis for this. Modify getTodos with this code:

我们需要做的最后一件事是change ./todo get仅显示已完成的任务。 我们将为此使用表情符号。 使用以下代码修改getTodos

todo
去做
//...
function getTodos() {
  const todos = db.get('todos').value()
  let index = 1;
  todos.forEach(todo => {
    let todoText = `${index++}. ${todo.title}`
    if (todo.complete) {
      todoText += ' ✔ ️' // add a check mark
    }
    console.log(chalk.strikethrough(todoText))
  })
  return
}
//...

When you now type in the ./todo get you’ll see this.

现在,输入./todo get您将看到此内容。


   
Output
1. Take a Scotch course 2. Travel the world ✔ ️ 3. Rewatch Avengers

结论 (Conclusion)

You’ve written two CLI applications in Node.js.

您已经在Node.js中编写了两个CLI应用程序。

Once your app is working, put the file into a bin folder. This way, npm knows how to work with the executable when you distribute it. Also, regardless of where you place the executable, you should update package.json bin property.

应用程序正常运行后,将文件放入bin文件夹。 这样,npm知道在分发可执行文件时如何使用它。 另外,无论将可执行文件放置在哪里,都应更新package.json bin属性。

The focus for this article was to look at how CLI applications are built with vanilla nodejs, but when working in the real world, it would be more productive to use libraries.

本文的重点是研究如何使用普通的nodejs构建CLI应用程序,但是在现实世界中工作时,使用库会更有效率。

Here’s a list of helpful libraries to help you write awesome CLI applications, which you can publish to npm.

以下是有用的库列表,可帮助您编写出色的CLI应用程序,并将其发布到npm。

  1. vopral - fully featured interactive CLI framework

    vopral-功能齐全的交互式CLI框架

  2. meow - CLI helper library

    喵 -CLI帮助程序库

  3. commanderjs - CLI library

    commanderjs -CLI库

  4. minimist - for arguments parsing

    极简主义者 -用于参数解析

  5. yargs - arguments parsing

    yargs-参数解析

And not to mention libraries like chalk that helped us with colors.

更不用说像粉笔这样的库了,可以帮助我们获得色彩。

As an additional exercise, try to add a Delete command to the CLI.

作为其他练习,请尝试将Delete命令添加到CLI。

翻译自: https://www.digitalocean.com/community/tutorials/how-to-build-command-line-applications-with-node-js

node.js启动应用命令


http://www.niftyadmin.cn/n/3649630.html

相关文章

[p2p]手机是否可以通过JXTA网络与PC机/PocketPC/WindowsMobile实现P2P呢?

本文只是探讨一下这种可能性。粗粗地看了JXTA&#xff0c;他的目标很宏大&#xff0c;不局限于各种设备&#xff0c;不局限于各种平台&#xff0c;只要能够保持心跳&#xff0c;就算是P2P的一个对等实体。下载并运行了myJXTA&#xff0c;还可以。又看了JXTA的J2ME实现&#xff…

Android项目实战系列—基于博学谷(六)习题模块

由于这个模块内容较多,篇幅较长&#xff0c;请耐心阅读。 习题模块分为两个部分 习题列表界面 习题详情界面 一、习题列表界面 1、习题界面 &#xff08;1&#xff09;、创建习题界面 在res/layout文件夹中&#xff0c;新建一个布局文件&#xff0c;命名为main_view_exercis…

dart mixins_Dart中的Mixins简介

dart mixinsSome of the best reasons for using object-oriented programming (OOP) are its techniques for helping to keep our code clean and DRY. We’re going to explore some of Dart’s strategies for making your code reusable over separate classes. 使用面向对…

[J2ME]RSSOwlMidlet(RSS无线阅读器)设计说明

郑昀ultrapower产品名称产品版本Keyword: RssReader RssFeed Channel j2me midp midlet kxml xmlpull RMS RssOwl java RSS无线阅读器0.7.1729[J2ME][开源]RSSOwlMidlet(RSS无线阅读器)设计说明我的RssReader资源&#xff1a;1&#xff1a;《[J2ME]RSSOwlMidlet(RSS无线阅读器…

Android项目实战系列—基于博学谷(七)课程模块(上)

由于这个模块内容较多,分为上、中、下 三篇博客分别来讲述&#xff0c;请耐心阅读。 课程模块分为四个部分 课程列表 课程详情 视频播放 播放记录 课程模块&#xff08;上&#xff09;主要讲述课程列表部分 一、水平滑动广告栏界面 1、创建水平滑动广告栏界面 在res/layout文…

Android:安卓开发采用Volley网络框架+MySQL数据库,实现从服务器获取数据并展示完成记单词APP

一、功能与要求 实现功能&#xff1a;设计一个记单词APP。服务器采用Tomcat&#xff0c;数据库采用Mysql。实现用户的注册登录功能以及单词的增删改查。 指标要求&#xff1a;实现UI布局&#xff1b;将系统数据保存到Mysql数据库中&#xff0c;并采用Volley网络框架实现从服务…