先安装express
新建一个文件夹如nodeApi,进入,然后npm init,会生成package.json
之后npm i express安装完express
新建index.js
最简单的监听服务器
const express = require('express');
const app = express();
//以上两行为标准动作
app.get('/', (req, res) => {
res.send('hello world');
//res.send([1,2,3]);返回数组
});
//req是指request, res是指response
//话说后面的function(req, res)好像不用写function了,是直接把function省略掉了吗?
app.listen(3000, ()=>console.log('listening on port 3000...'));
//此处好像也是把function省略掉了
之后终端输入node index.js
之后浏览器localhost:3000可以看到hello world
使用nodemon持续监听
如果用node index.js的话,每次修改文件都需要ctrl+c取消重新启动
安装nodemon(node monitoring)就可以不用手工重启
修改端口避免冲突
const port = process.env.PORT || 3000; //使用环境端口或者3000。我有点好奇,如果3000被占用了
app.listen(port, ()=>console.log(`listening to port ${port}...`));
//监听port,后面为啥用``和${port}就可以插入变量?第一次看见这个
//不过我使用set PORT=5000之后,listen还是在3000,不知道为什么
获取路径中的基础参数
app.get('/api/courses/:id', (req, res)=>{
res.send(req.params.id);
});
//可以使用req.params.id来获取id这个参数,
//可以有多个参数,比如/api/courses/:id/:name/:age
获取问号后的查询参数
app.get('/api/courses/:id', (req, res)=>{
res.send(req.query);
});
//在这里的路径里并不需要定义,query就可以自动把问号后的记录下来
通过参数查询数据
假设有个课程列表
const courses = [
{ id: 1, name: 'course1'},
{ id: 2, name: 'course2'},
{ id: 3, name: 'course3'}
];
app.get('/api/courses/:id', (req, res)=>{
const course = courses.find(c => c.id === parseInt(req.params.id));
//使用courses.find方法,通过c.id等于传入的id来查询,parseInt是把文本转成数字的方法
//至于c => c.id是什么操作,我还是不太明白这个箭头函数
if (!course) res.status(404).send('the course is not found'); //返回404状态码,并send错误信息
res.send(course) //如果course不为空,返回course
//这个if () true第二行false的写法,也是第一次见到...
});
此时访问localhost:3000/api/courses/1,会获得返回的course,是一个json格式的
{id:3, name:'course1'}
如果访问localhost:3000/api/courses/4,会获得返回的错误信息
使用post方法新增数据
app.use(express.json());
//需要使用这个组件,要不然的话不能使用courses.push操作json数据(应该是这样的吧...)
app.post('/api/courses', (req, res) => {
const course = {
id: courses.length + 1,
name: req.body.name //注意post的内容是通过req.body来获得的
};
courses.push(course); //将新增的course添加到courses里
res.send(course); //返回新增的数据
});
这里需要使用postman来进行验证测试
安装postman,选择post,URL:http://localhost:3000/api/courses
选择body, 选择raw,选择JSON(application/json)
然后输入:
{
"name":"new course"
}
点击“发送”,在console里会收到返回的数据
{
"id": 4,
"name": "new course"
}
添加验证
如果post过来的参数不符合要求,就需要做验证
app.post('/api/courses', (req, res) => {
if (!req.body.name || req.body.name.length < 3) { //如果name是空的,或者长度小于3
res.status(400).send('name can\'t be null and minimun 3 characters');
return; //这里用return来阻止后面代码的运行
}
const course = {
id: courses.length + 1,
name: req.body.name //注意post的内容是通过req.body来获得的
};
courses.push(course); //将新增的course添加到courses里
res.send(course); //返回新增的数据
});
使用post可以测试验证是否正常
使用Joi验证组件
因为每一次都写各种验证器太繁琐,于是有了Joi这个验证管理组件(我觉得是这样)
使用npm i joi@13.1.0安装视频中的版本
在最上面引入,const Joi = require('joi');
创建一个schema,里面包含了每个字段的格式要求
const schema = {
name: Joi.string().min(3).required //string格式、最小3字符、必填
};
接着使用validate
const result = Joi.validate(req.body, schema); //使用schema的规则去验证req.body
console.log(result); //可以查看验证结果
如果验证成功,result.error就是null,可以用这个来判断进行下一步操作
修改之前的代码:
if (!req.body.name || req.body.name.length < 3) { //如果name是空的,或者长度小于3
res.status(400).send('name can\'t be null and minimun 3 characters');
return; //这里用return来阻止后面代码的运行
}
改成:
if (result.error) { //如果error不为空,表示验证失败,返回失败信息
res.status(400).send(result.error.details[0].message);
return; //这里用return来阻止后面代码的运行
}
使用put更新信息
app.put('/api/courses/:id', (req, res) => {
//根据id查看是否能找到课程
const course = courses.find(c => c.id === parseInt(req.body.id));
if (!course) res.send('can not find the course by id');
//验证参数是否符合规则
const schema = {
"name": Joi.string().min(3).required()
};
const result = Joi.validate(req.body, schema);
if (result.error) {
res.status(400).send(result.error.details[0].message);
return;
}
//更新参数值
course.name = req.body.name;
//返回更新后的数据
res.send(course);
});
将validate方法独立出来
function validateCourse(course){
const schema = {
"name": Joi.string().min(3).required()
};
return result = Joi.validate(course, schema);
}
然后在前面需要使用的地方调用此方法
const result = validateCourse(req.body);
这里有个方法,如果我们关注的是result里的error,一般我们会使用result.error来获取,但有个更加简洁的办法,就是直接使用:
const { error } = validateCourse(req.body);
就可以直接获取error里面的信息了。
把之前post方法里的验证部分,也改成这样,只需要copy过去就可以了。
**使用delete方法
app.delete('/api/courses/:id', (req, res) => {
//查找是否有此课程
const course = courses.find(c => c.id === parseInt(req.params.id));
if (!course) res.status(404).send('The course with given ID was not found');
//删除此课程
//需要获取通过id找到的course的index,然后通过index并使用splice方法来删除课程
const index = courses.indexOf(course);
courses.splice(index, 1);
//返回删除成功
res.send(course);
});
简洁代码判断查找成功与否
判断是否能找到课程,之前是这么写的:
//查看是否能找到
const course = courses.find(c => c.id === parseInt(req.params.id));
if (!course) res.status(404).send('The course with given ID was not found');
return;
更好的写法是:
if (!course) return res.status(404).send('The course with given ID was not found');
//如果没有找到course,就返回404和错误信息,如果找到了,就执行后面的代码,一行就表达清楚了
验证内容是否符合要求,之前是这么写的:
//验证内容
const { error } = validateCourse(req.body);
if (error){
//400 bad request
res.status(400).send(error.details[0].message);
return;
}
同样可以应用上面的代码,使其更加简洁:
//验证内容
const { error } = validateCourse(req.body);
if (error) return res.status(400).send(error.details[0].message);
....
完整代码
const Joi = require('joi');
const express = require('express');
const app = express();
app.use(express.json());
const courses = [
{ id: 1, name: 'course1'},
{ id: 2, name: 'course2'},
{ id: 3, name: 'course3'}
];
app.get('/', (req, res) => {
res.send('hello world');
});
app.get('/api/courses', (req, res) => {
res.send(courses);
});
app.get('/api/courses/:id', (req, res) => {
const course = courses.find(c => c.id === parseInt(req.params.id));
if (!course) return res.status(404).send('The course with given ID was not found');
res.send(course);
});
app.post('/api/courses', (req, res) => {
//验证内容
const { error } = validateCourse(req.body);
if (error) return res.status(400).send(error.details[0].message);
const course = {
id: courses.length + 1,
name: req.body.name
};
courses.push(course);
res.send(course);
});
app.put('/api/courses/:id', (req, res) => {
//查看是否能找到
const course = courses.find(c => c.id === parseInt(req.params.id));
if (!course) return res.status(404).send('The course with given ID was not found');
//验证内容
const { error } = validateCourse(req.body);
if (error) return res.status(400).send(error.details[0].message);
//更新name //为什么course是const又能改呢?
course.name = req.body.name;
//返回更新的信息
res.send(course);
});
app.delete('/api/courses/:id', (req, res) => {
//查找是否有此课程
const course = courses.find(c => c.id === parseInt(req.params.id));
if (!course) return res.status(404).send('The course with given ID was not found');
//删除此课程
const index = courses.indexOf(course);
courses.splice(index, 1);
//返回删除成功
res.send(course);
});
function validateCourse(course){
const schema = {
name: Joi.string().min(3).required()
};
return Joi.validate(course, schema);
};
const port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Listening on part ${port}...`));
课程总结
这个课程学习到了对数据的增删改查,我觉得还是很简单易懂的,老外的教程的确很不错。
我现在要克服一个MVC的思维,总觉得一定要在一个程序里面写MVC,但其实这种前后端分离的写法更加科学,前端我只需要用vue.js来调取api对数据进行增删改查就可以了,后端只需要响应前端的请求就可以了,没有必要一定要像thinkphp那样,把所有mvc都写在一套程序里。
另外一个缺点就是这个教程没有对数据库操作的部分,只好到另一个教程上去学了。
最新回复