Node.js fs模塊學習

通過一個簡單的 node 命令行的 todo 項目學習了 nodejs 文件模塊,收獲頗多。

Github 源碼

項目介紹:

  • 功能
    可以展示所有 todo 任務
    可以新創(chuàng)建一個任務
    可以編輯 todo 任務,修改任務名、完成狀態(tài)
    可以刪除 todo 任務
  • 命令

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

  • 展示

引入 node fs模塊

nodejs fs 中文文檔

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

path (被讀取文件路徑);
options (文件以什么形式被讀取,flag: a+ 打開文件進行讀取和追加,如果文件不存在,則創(chuàng)建該文件);
cllback (回調函數(shù),讀取文件之后的操作,接受兩個參數(shù),Error 讀取文件失敗結果,data 讀取成功結果)

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

file (被寫入的文件路徑);
data (文件被寫入的內(nèi)容);
cllback (回調函數(shù),讀取文件之后的操作,只接受一個參數(shù),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() 來自定義命令;

需要通過獨立的的可執(zhí)行文件來實現(xiàn)命令,如index.js,自定義命令的執(zhí)行部分主要放在這里;

.action((arg)=>{}) 調用可執(zhí)行文件 index.js 中對應的函數(shù);

.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 : 后續(xù)在 .then() 時使用來操作answer 的 key;
message : 命令行提示信息,通常是一個詢問;
choices : 數(shù)組或返回一個選擇數(shù)組的函數(shù),如果定義為函數(shù),則第一個參數(shù)將是當前會話的 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 可實現(xiàn)各種層級的命令行交互界面;
此時即可通過 node cli 可執(zhí)行查看任務列表,并進行后續(xù)的交互操作;
通過 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 主要用于在修改后的環(huán)境中運行命令。寫 /usr/bin/env node 告訴 OS 運行 env,而 env 將運行 node,最后 node 將依次執(zhí)行腳本。

命令行工具配置

package.json 中添加 bin 屬性,指定命令的名稱

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

發(fā)布至 npm

  1. package.json 添加 files 屬性,確定要上傳包的文件,上傳所有 .js 文件
  "files": [
    "*.js"
  ],
  1. 保證 name 不會與現(xiàn)有的 npm 包重名;
  2. 輸入 npm login 登錄賬戶,注意使用 nrm use npm 切換為 npm 源然后登錄;
  3. 登錄之后使用 npm publish 發(fā)布。
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容