Node js 文件模块

95 阅读2分钟

写了一个todo list来了解Node js的文件模块

cli.js 入口文件

引入commander 文档

npm install commander

const program = require('commander');
const api = require('./index.js')

program
    .option('-x,--xxx','what the x');
//flags description
program
    .command('add')
    //选项的参数使用方括号声明表示参数是可选参数
    .description('add a task')
    .action( (...args)=>{
        const words = args.slice(0,-1).join(' ')
    //使用方括号后,如果输入多个单词只会记录第一个,使用args录入多个单词后最后一位是command命令需要删除
        api.add(words).then(()=>{console.log("添加成功")},()=>{console.log("添加失败")})
    });

program
    .command('clear')
    .description('clear all tasks')
    .action( ()=>{
        api.clear().then(()=>{console.log("清除成功")},()=>{console.log("清除失败")})
    })
program.parse(process.argv);
if(process.argv.length === 2){
    //说明用户直接运行node cli.js
    void api.showAll()
}

index.js 封装相关操作的文件

这里的命令行交互操作使用了inquirer(文档)库来实现的

npm install inquirer

const db = require('./db.js')
const inquirer = require('inquirer')

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

module.exports.clear = async(title) =>{
    await db.write([])
}

module.exports.showAll = async(title) =>{
    const list = await db.read()
    list.forEach((task,index)=>{
        console.log(`${task.done ?'[x]':'[√]'} ${index+1}-${task.title}`)
    })
    inquirer
    .prompt([
        {
        type: 'list',
        name: 'index',
        message: '请选择你想操作的任务',
        choices: [
            {name:'退出',value:'-1'},

            ...list.map((task,index)=>{
                return {name:`${task.done ? '[√]' : '[x]'} ${index + 1} - ${task.title}`,value:index.toString()}
            }),
            {name:'+ 创建任务',value:'-2'},
            {name:'全部删除',value:'-3'}
            ],
        },
    ])
    .then((answer) => {
        const index = parseInt(answer.index)
       if(index >= 0 ){
        inquirer.prompt({
            type:'list',name:'action',
            message:'请选择操作',
            choices:[
                {name:'退出',value:'quit'},
                {name:'已完成',value:'markAsDone'},
                {name:'未完成',value:'markAsUndone'},
                {name:'改标题',value:'updateTitle'},
                {name:'删除',value:'remove'},
            ]
        }).then(answer2 =>{
            switch(answer2.action){
                case 'markAsDone':
                    list[index].done = true
                    break;
                case 'markAsUndone':
                    list[index].done = false
                    break;
                case 'updateTitle':
                    inquirer.prompt(
                        {
                            type: 'input',
                            name: 'title',
                            message: "新的标题",
                            default:list[index].title
                        }
                    ).then((answer) => {
                        list[index].title = answer.title
                        db.write(list)
                      });
                        break;
                case 'remove':
                    list.splice(index,1)
                    db.write(list)
                    break;
            }
        })
       }else if(index === -2 ){
            //取名
            inquirer.prompt(
                {
                    type: 'input',
                    name: 'title',
                    message: "输入新的任务",
                }
            ).then((answer) => {
                list.push({
                    title:answer.title,
                    done:false,
                })
                db.write(list)
              });
       }else if(index === -3){
        inquirer.prompt(
            {
                type: 'input',
                name: 'title',
                message: "确实要全部删除吗?删除请输入Y,退出输入其他",
            }
        ).then((answer) => {
            if(answer.title === 'y'||answer.title === 'Y')
            {
                list.splice(0)
                db.write(list)
                console.log("删除成功")
            }
          });
       }
    });
}


db.js 文件的读写封装


const fs = require('fs')
const homedir = require('os').homedir()
//系统根目录
const home = process.env.HOME;
//HOME配置目录 一般同上
const p = require('path')
const dbPath = p.join(home,'.todo')

const db = {
    read(path = dbPath) {
        return new Promise((resolve,reject)=>{
            fs.readFile(path,{flag:'a+'},(error,data)=>{
                //"a+"如果没有文件则创建
                if(error)
                {
                    console.log(error)
                    reject(error)
                }
                else {
                    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

更多详细内容可以看我的github笔记

这里用的commander版本较老3.0.2,换成新版可能有bug