1 // express_demo.js 文件
2 const fs = require('fs')
3
4 // 引入 express 并且创建一个 express 实例赋值给 app
5 const express = require('express')
6 const bodyParser = require('body-parser')
7
8 // 如果引入的模块省略了后缀名, 会找相应的 js 文件或者 json 文件
9 const { log } = require('./utils')
10
11 // const log = require('./utils').log
12 // 上面这行代码相当于下面两行代码
13 // const a = require('./utils')
14 // const log = a.log
15 // {
16 // 'log': log,
17 // }
18
19 // new 一个 express 实例
20 const app = express()
21
22 const todoList = []
23
24 // 配置静态文件目录
25 app.use(express.static('asset'))
26 // 注意
27 // 1. app.use 第一个必须是 static
28 // 2. bodyParser.json() 表示会自动解析 json 格式的数据
29 app.use(bodyParser.json())
30
31 const sendHtml = (response, path) => {
32 let options = {
33 encoding: 'utf-8',
34 }
35 fs.readFile(path, options, (error, data) => {
36 // log(`读取的 html 文件 ${path} 内容是\n`, data)
37 // 表示把响应发送到客户端
38 response.send(data)
39 })
40 }
41
42 const sendJSON = (response, data) => {
43 let r = JSON.stringify(data)
44 response.send(r)
45 }
46
47 // 用 get 定义一个给用户访问的网址
48 // request 是浏览器发送的请求
49 // response 是我们要发给浏览器的响应
50 // get 表示请求方法是 GET
51 // / 表示请求 path 是 /
52 // app.get('/', () => {}) 表示以 GET 方法访问 / 这个 path
53 // 会调用 () => {} 这个回调函数
54 app.get('/', (request, response) => {
55 let path = 'index.html'
56 sendHtml(response, path)
57 })
58
59 app.get('/todo/all', (requrest, response) => {
60 sendJSON(response, todoList)
61 })
62
63 const todoAdd = (form) => {
64 // 给新增的 todo 增加 id 属性
65 // 在 todoList.push 之前
66 // 如果 todoList 里面有 todo
67 // todo.id 就是 todoList 里最后一个 todo 的 id + 1
68 // 如果 todoList 没有 todo
69 // todo.id 为 1
70 if (todoList.length === 0) {
71 form.id = 1
72 } else {
73 let tailTodo = todoList[todoList.length - 1]
74 form.id = tailTodo.id + 1
75 }
76 todoList.push(form)
77 return form
78 }
79
80 app.post('/todo/add', (request, response) => {
81 let form = request.body
82 let todo = todoAdd(form)
83 sendJSON(response, todo)
84 })
85
86 const todoDelete = (id) => {
87 id = Number(id)
88 let index = -1
89 for (let i = 0; i < todoList.length; i++) {
90 let t = todoList[i]
91 if (t.id === id) {
92 index = i
93 break
94 }
95 }
96
97 // 通过判断 index 的值来查看是否找到了这个 todo
98 if (index > -1) {
99 let t = todoList.splice(index, 1)[0]
100 return t
101 } else {
102 return {}
103 }
104 }
105
106
107 // delete 这个路由函数用了一个叫做 动态路由 的概念
108 // 其中 :id 是一个动态变量
109 // 它可以匹配如下 url
110 // /todo/delete/1
111 // /todo/delete/2
112
113 // 甚至可以匹配下面的 url
114 // /todo/delete/error
115 app.get('/todo/delete/:id', (request, response) => {
116 // 动态路由的变量通过 request.params.id 的方式获取
117 // 变量类型永远是 string
118 let id = request.params.id
119 let todo = todoDelete(id)
120 sendJSON(response, todo)
121 })
122
123 const main = () => {
124 // listen 函数的第一个参数是我们要监听的端口
125 // 这个端口是要浏览器输入的
126 // 默认的端口是 80
127 // 所以如果你监听 80 端口的话,浏览器就不需要输入端口了
128 // 但是 1024 以下的端口是系统保留端口,需要管理员权限才能使用
129 let server = app.listen(5000, () => {
130 let host = server.address().address
131 let port = server.address().port
132
133 log(`应用实例,访问地址为 http://${host}:${port}`)
134 })
135 }
136
137 // 这个是套路写法
138 if (require.main === module) {
139 main()
140 }