一. 优化之前的代码
- 我们理清楚整个逻辑之后,期望实现的api
module.exports.add = (title) => {
// 读取之前代码
const list = db.read()
// 往里面添加一个 title 任务
list.push({title, done: false})
// 存储任务到文件
db.write(list)
}
- 创建db.js,并使用promise实现read
// 这是直接获取系统的home目录
const homedir = require('os').homedir();
// 这是用户设置的home目录环境变量
const home = process.env.HOME || homedir
// 拼接储存文件路径
const p = require('path')
const dbPath = p.join(home, '.todo')
const fs = require('fs')
const db = {
read(path = dbPath) {
return new Promise((resolve, reject)=>{
fs.readFile(path, { flag: 'a+' }, (error, data) => {
if(error) {
console.log('error', error)
reject(error)
} else{
let list
try {
list = JSON.parse(data.toString())
} catch (error2) {
list = []
}
resolve(list)
}
})
})
}
write() {}
}
modules.exports = db
- 写好write
write(list, path = dbPath) {
return new Promise((resolve, reject) => {
const string = JSON.stringify(list)
fs.writeFile(dbPath, string, (error)=>{
if(error) return reject(error)
resolve()
})
})
}
- 最终优化后的代码
// index.js
const db = require('./db.js')
module.exports.add = async (title) => {
// 读取之前代码
const list = await db.read()
// 往里面添加一个 title 任务
list.push({title, done: false})
// 存储任务到文件
await db.write(list)
}
// db.js
// 这是直接获取系统的home目录
const homedir = require('os').homedir();
// 这是用户设置的home目录环境变量
const home = process.env.HOME || homedir
// 拼接储存文件路径
const p = require('path')
const dbPath = p.join(home, '.todo')
const fs = require('fs')
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, (error)=>{
if(error) return reject(error)
resolve()
})
})
}
}
module.exports = db
- 总结: 我们通过先理清楚思路,设计好接口,再把之前的代码一点点挪过去来优化代码,我们称这种方法叫做面向接口编程
二. 消除webstorm警告
- 需要打开webstorm的配置,见下图,如果没有找到需要下载一下,下载需要开代理
三. 实现剩下的代码
- 实现clear
// cli.js
program
.command('clear')
.description('clear all tasks')
.action(() => {
api.clear()
});
// index.js
module.exports.clear = async (title) => {
await db.write([])
}
- 实现展示全部
module.exports.showAll = async () => {
// 读取之前的任务,
const list = await db.read()
// 打印之前的任务
list.forEach((task, index)=>{
console.log(`${task.done ? '[x]' : '[_]'} ${index + 1} - ${task.title}`)
})
}
四. 通过inquirer.js来实现选择勾选完成等功能
npm install inquirer
- 主要的代码逻辑
// cli.js
if(process.argv.length === 2) {
// 说明用户直接运行 node cli.js
api.showAll().then(()=>{console.log('')}, ()=>{console.log('展示失败')})
}
// index.js
module.exports.showAll = async () => {
// 读取之前的任务,
const list = await db.read()
// 打印之前的任务
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'}]
},
])
.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
db.write(list)
break;
case 'markAsUndone':
list[index].done = false
db.write(list)
break;
case 'updateTitle':
inquirer.prompt({
type: 'input',
name: 'title',
message: '请输入新的标题:',
default: list[index].title
}).then(answers => {
list[index].title = answers.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)
})
}
});
}