Node.js fs模块学习

通过一个简单的 node 命令行的 todo 项目学习了 nodejs 文件模块,收获颇多。

Github 源码

项目介绍:

  • 功能
    可以展示所有 todo 任务
    可以新创建一个任务
    可以编辑 todo 任务,修改任务名、完成状态
    可以删除 todo 任务
  • 命令

    d 展示所有任务
    d add xxx 添加新任务
    d clear 清除所有任务

  • 展示

引入 node fs模块

nodejs fs 中文文档

  1. fs.readFile(path[, options], callback)

path (被读取文件路径);
options (文件以什么形式被读取,flag: a+ 打开文件进行读取和追加,如果文件不存在,则创建该文件);
cllback (回调函数,读取文件之后的操作,接受两个参数,Error 读取文件失败结果,data 读取成功结果)

  1. fs.writeFile(file, data[, options], callback)

file (被写入的文件路径);
data (文件被写入的内容);
cllback (回调函数,读取文件之后的操作,只接受一个参数,Error 写入文件失败结果)

  1. 读文件与写文件都是异步操作,所以需要返回一个 promise 对象,调用 read()write() 时需要使用 awaitasync,如果读取或者写入文件失败,则 callback() 传入的 error 需要使用 reject(error) 返回。
  2. 导入文件时使用 require('xxx') ,导出时使用 module.exports
// db.js

// 配置 .todo 文件到 home 目录
const homedir = require('os').homedir()
const home = process.env.HOME || homedir
const p = require('path')
const fs = require('fs')
const dbPath = p.join(home, '.todo')

const db = {
  // 读取之前的任务
  read(path = dbPath) {
    return new Promise((resolve, reject) => {
      fs.readFile(path, {flag: 'a+'}, (error, data) => {
        if (error) {return reject(error)}
        let list
        try {
          list = JSON.parse(data.toString())
        } catch (error2) {
          list = []
        }
        resolve(list)
      })
    })
  },
  // 存储任务到文件
  write(list, path = dbPath) {
    return new Promise((resolve, reject) => {
      const string = JSON.stringify(list)
      fs.writeFile(path, string + '\n', (error) => {
        if (error) {return reject(error)}
        resolve()
      })
    })
  }
}

module.exports = db

引入 commander.js 配置命令

commander.js 是完整的命令行解决方案;

安装并引入之后可以通过 .command() 来自定义命令;

需要通过独立的的可执行文件来实现命令,如index.js,自定义命令的执行部分主要放在这里;

.action((arg)=>{}) 调用可执行文件 index.js 中对应的函数;

.description() 用来描述命令干了什么。

//  cli.js  (add示例)
const program = require('commander');
const api = require('./index')

program
  .command('add')
  .description('add a task')
  .action((...args) => {
    const words = args.slice(0, -1).join(' ')
    api.add(words)
      .then(() => {console.log('添加成功')}, () => {console.log('添加失败')})
  });

program.parse(process.argv);
//  index.js (add示例)
const db = require('./db')

module.exports.add = async (title) => {
  // 读取之前的任务
  const list = await db.read()
  // 添加一个新任务
  list.push({title: title, done: false})
  // 存储任务到文件
  await db.write(list)
}

注意:添加和清空任务后都要将新的任务列表写入文件。

引入 inquirer.js

Inquirer.js 是一个命令行交互工具;

安装并引入后通过 inquirer.prompt({type, name, message, choices[fn]}).then((answer)=>{}) 来配置命令行操作界面;

type : prompt 的类型. 默认值: input 可选值: input, number, confirm, list, rawlist, expand, checkbox, password, editor
name : 后续在 .then() 时使用来操作answer 的 key;
message : 命令行提示信息,通常是一个询问;
choices : 数组或返回一个选择数组的函数,如果定义为函数,则第一个参数将是当前会话的 answer
answer : 由一个键值对组成,key 是该 prompt 的 name 属性,value 取决于 prompt 的类型,在这里是每一项任务。

//  index.js  (askForAction示例)
const inquirer = require('inquirer')

module.exports.show = async () => {
  // 读取之前的 list
  const list = await db.read()
  // 切换进行操作任务
  printTasks(list)
}

function printTasks(list) {
  inquirer
    .prompt({
      type: 'list',
      name: 'index',
      message: '请选择需要操作的任务',
      choices: [...list.map((item, index) => {
        return {
          name: `${item.done ? '[√]' : '[x]'}${index + 1}:${item.title}`, value: index.toString()
        }
      }), {name: ' + 添加', value: '-1'}, {name: ' x 取消', value: '-2'}]
    }).then((answer) => {
    const index = parseInt(answer.index)
    if (index >= 0) {
      askForAction(list, index)
    } else if (index === -1) {
      askForCreatTask(list)
    }
  })
}

通过嵌套 inquirer 可实现各种层级的命令行交互界面;
此时即可通过 node cli 可执行查看任务列表,并进行后续的交互操作;
通过 node cli add 添加任务,node clear 清除任务列表;
但是这样每次必须要都输入 node。

Node.js 使用 Shebang

当对 cli.js 文件设置了正确的 Shebang 时,只需输入 ./cli.js 即可

设置方法:

  • 命令行输入
 chmod u+x cli.js 
  • cli.js 文件首行输入
#!/usr/bin/env node

env 主要用于在修改后的环境中运行命令。写 /usr/bin/env node 告诉 OS 运行 env,而 env 将运行 node,最后 node 将依次执行脚本。

命令行工具配置

package.json 中添加 bin 属性,指定命令的名称

  "bin": {
    "d": "cli.js"
  },

发布至 npm

  1. package.json 添加 files 属性,确定要上传包的文件,上传所有 .js 文件
  "files": [
    "*.js"
  ],
  1. 保证 name 不会与现有的 npm 包重名;
  2. 输入 npm login 登录账户,注意使用 nrm use npm 切换为 npm 源然后登录;
  3. 登录之后使用 npm publish 发布。

你可能感兴趣的:(Node.js fs模块学习)