使用node.js创建一个todo列表——node.js服务器搭建、json读写以及使用pm2保持服务运行

使用node.js创建一个todo列表——node.js服务器搭建以及json读写

前言

前些日子学习了 nodejs ,顺理成章的想要找点东西练练手。恰好最近需要一个简介的todo list网页,因为之前用的一些todo list应用都被墙了,访问速度感人,于是就想自己搞一个todo。

而恰好,我要搞的todo是一个非常简单的程序,非常适合用nodejs这样的解释型脚本语言来实现,比起java这样光搭框架就要半天的专注大型项目的语言,nodejs 的优势就是非明显了。

nodejs搭建服务器只需要去nodejs官网复制这样的一块代码:

1
2
3
4
5
6
7
8
const express = require('express')
const app = express()

app.get('/', (req, res) => {
res.send('Hi!')
})

app.listen(3000, () => console.log('Server ready'))

所以我们可以把更多的经历放在我们的业务实现上。

准备工作

需求分析

在开始动工之前,要先列出需求。当时我的需求如下:

  • 添加需要做的事情

  • 展示需要做的事情

  • 完成需要做的事情

  • 查看曾经完成的事情

解决方案分析

对于上述需求,我打算这样实现:

  • 使用json文件系统实现持久化操作

  • 使用nodejs来获取数据

  • 使用nodejs来处理数据并储存数据

这样的话。明确了需求与实现方式,我们就可以动工了。

实现

json读写

nodejs提供了一套文件的读写的模块:fs。使用fs可以很简单的实现文本文件的读写。但是为了我们在开发的时候更加方便,我又将他封装成了一个专注json读写的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//in jsonHandler.js
const fs = require("fs");

function test(){
console.log("Hello world!")
}
function readJson(name){
let jsonFile = fs.readFileSync("./"+name);
let toDoList = JSON.parse(jsonFile); //解析json,并直接返回json对象
return toDoList;
}
function writeJson(name,data){
fs.writeFileSync("./"+name,JSON.stringify(data));
}

module.exports = {
readJson,
writeJson
}

服务器搭建

还记得我们的服务器的格式吗?我们先定义一下我们的服务器接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//in index.js
const jh = require("./jsonHandler")
const http = require('http');
const url = require('url');
const util = require('util');

let workList = jh.readJson("list.json");

const port = 3000

const server = http.createServer((req, res) => {
//设置响应头与请求编码
res.statusCode = 200
//设置字节流编码为utf-8
res.setHeader('Content-Type', 'text/plain;charset=utf8')
//设置允许跨域
res.setHeader('Access-Control-Allow-Origin','*')
req.setEncoding('utf8');

//write your code here

let ret=""; //这是需要返回的数据
res.end(ret)
})

server.listen(port, () => {
})

然后根据我们的需求分析,先来确定以下API接口:

  • addWork():用来添加一个任务并将数据保存到json

  • deleteWord(res):用来将一个任务删除并将数据保存到json

  • writeHistory(work):将完成的任务添加到历史记录中

  • getAllWork():获取目前正在运行中的任务

首先我们先开始addWork()的编写,要添加的话,首先要接受并解析客户端发送的请求,然后再储存到json中,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//用来增加一个任务
function addWork(){
let work="";
req.on('data', chunk => { //接受客户端发送的请求流
//这里要取子串的原因是请求会带key,我这里是work=xxx,所以要将'work='去掉
work=chunk.toString().substring(5);
//设置编码,不然中文会乱码
work = decodeURIComponent(work);
//解析worklist
let jsonObj=eval(workList)
jsonObj.push({"work":work})
//将数据写回
jh.writeJson("list.json",jsonObj)
})
}

任务历史与添加任务几乎同理,只不过这个方法获取的数据是deleteWork提供的,我们不需要再去监控客户端的请求。代码如下:

1
2
3
4
5
6
7
8
9
10
//任务历史
function writeHistory(work) {
let jsonStr = jh.readJson("history.json");
let jsonObj = eval(jsonStr);
let event = {}
event.work = work;
event.finishTime =new Date();
jsonObj.push(event);
jh.writeJson("history.json",jsonObj)
}

删除任务也是同理,我们要在前端给每个任务隐性的标上index,然后就可以用来删除了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//删除任务
function deleteWork(res){
req.on('data', chunk => {
console.log(`可用的数据块: ${chunk}`)
//获取点击事件的位置
let index=chunk.toString().substring(3);
let jsonObj=eval(workList)
//添加历史
let work = jsonObj[index].work
writeHistory(work)
//删除
jsonObj.splice(index,1);
// console.log(jsonObj)
jh.writeJson("list.json",jsonObj)
})
}

获取任务就非常简单了,我们只需要从json中拿到数据并转发给客户端就可以了:

1
2
3
4
5
//获取所有任务
function getAllWork(){
workList=jh.readJson("list.json");
ret=JSON.stringify(workList);
}

最后呢,我们需要写一个路由解析,因为js非常小,所以这些东西都写在一个文件里面就可以:

1
2
3
4
5
6
7
8
9
10
11
12
/解析路由
let pathname = url.parse(req.url).pathname;
//路由配置
if (pathname==="/getAllWork"){
getAllWork()
}
else if(pathname==="/addWork"){
addWork()
}
else if(pathname==="/deleteWork"){
deleteWork()
}

随下贴出前端源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<-- in index.html -->
<!DOCTYPE html>
<html lang="ch">
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.simplecss.org/simple.css">
<link rel="stylesheet" type="text/css" href="technological.css">
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body class="tech-background" style="text-align: center">
<p> wish you a substantial day</p>
<p>to do list</p>
<label>
<input name="add-work" id="add-work" class="tech-input" style="width: 70%">
<button onclick='addWork()' class="tech-btn" style="display: inline;">增加</button>
</label>
<div id="container"></div>
<script>
'use strict'
$.ajax({
url:"http://localhost:3000/getAllWork",
method:"GET",
crossDomain: true,
success:(res)=>{
let con=document.getElementById("container");
let workList=JSON.parse(res)
console.log(workList)
workList=eval(workList)
for (let i=0;i<workList.length;i++){
let list=document.createElement("label");
list.innerHTML="<input name=\"work-list\" id=\"work"+i+"\" value='"+workList[i].work+"' class='tech-input' style=\"width: 70%\"> " +
"<button onclick='deleteWork(this)' id='"+i+"' class='tech-btn' style=\"display: inline;\">完成</button>";
con.appendChild(list);
}
}
})
function addWork(){
let work=document.getElementById("add-work").value;
$.ajax({
url: "http://localhost:3000/addWork",
method: "POST",
crossDomain: true,
data:{
"work":work
},
success:(res)=>{
// alert("success");
location.reload();
}
})
}
function deleteWork(res){
let index=res.id;
$.ajax({
url: "http://localhost:3000/deleteWork",
method: "POST",
crossDomain: true,
data:{
"id":index
},
success:(res)=>{
// alert("success");
location.reload();
}
})
}
</script>
</body>
</html>

这个项目的源码我也会放在GitHub(因为项目实在太小我甚至都没有建一个文件夹)

项目地址

保持代码运行

我们服务器代码当然要有一个服务器去运行,而这个迷你的项目显然不值得让我们去分配他一个云服务器加一个域名,那么我们是否可以把这个服务运行在本地呢?

可是运行在本地就需要频繁的重启服务,每次开机都要启动一次,这未免也太麻烦了。于是我们就可以使用pm2来使我们的项目保持运行

关于pm2我在此不多赘述了,大家有兴趣的可以自行百度搜索,我只给出部署的命令:

1
2
3
4
5
npm install pm2 -g #全局安装pm2
cd <项目目录>
pm2 start index.js --watch
pm2 save
pm2 list

如果你部署成功,那么当你运行pm2 list之后你就可以看到你的项目了


使用node.js创建一个todo列表——node.js服务器搭建、json读写以及使用pm2保持服务运行
2022/08/30/technology/program/to-do-list-by-nodeJS/
作者
charlesix59
发布于
2022年8月30日
许可协议