最近在学习node相关的知识,说到后台就少不了数据库等知识,综合查阅的资料,我使用的是koa+mongodb+mongoose.在这篇文章中我会详细介绍这个项目的搭建过程,以及开发过程中遇到的坑点以及需要注意的点,适合初学者快速入门。
本文后mvc台架构参考的是廖雪峰的koa mvc架构
后台搭建项目地址 koa-learn 代码才是硬道理。
对应的前端代码搭建过程,内含代码地址。 mixsys
mongoose连接mongoldb 这个最好看一下,涉及到一些项目介绍。
前端代码就是简单的react+redux的知识,框架搭建上面文章介绍的很详细,后期我加了一些增删改查的逻辑以及升级了网络访问的工具方法。
说到项目就要从入口开始说起,app.js
,一些基础的建表功能,上述mongoose连接mongodb中已有介绍,这里不多说。剩下的中间件我用的不多,但是node本身社区提供了大量优秀的中间件,你也可以自己编写中间件(下面的handler其实就是一个中间件),我就简单说说项目中用到的几个。
bodyParser()是解析网络访问发送的body数据的,比如Post请求发送用户名密码。
cors()是用于处理跨域问题的,跨域问题后端要允许跨域,前端也要支持跨域,两者缺一不可。
templateing是模板,通过后台访问,可以返回给浏览器一个web页面,参见浏览器中输入http://localhost:8080/
返回的页面,这就是自己定义的。
最重要的是controller(),这个是引入了你定义的所有一系列操作,在服务器启动的时候把你所有生命的处理函数都注册进来,是后台访问的初始化操作。
最后说一句,由于node洋葱模型,app.use()使用的数据是有先后分别的,要注意一下(参见下方错误处理,就要放在第一个来use())。
首先可以看到的就是我声明了一个handler变量,如下
const handler = async (ctx, next) => {
try {
await next()
} catch (error) {
ctx.response.body = {
error: true,
code: '00000',
message: '服务器异常',
desc: error.message
}
}
}
然后,在数据库连接成功之后,第一个就使用了app.use(handler)这个语句,这里我着重介绍一下这样写的原因。
在我们进行网络访问的时候,肯定不会所有的请求都不报错,那如果遇到报错就需要一个错误处理机制来处理错误,要保证前端调用人员知道错误的原因,而不是什么都不返回,任其抛出错误。
node的***洋葱模型***如果大家可以理解的话,看到这个语句,就知道这个catch语句时最后执行的,也就是说,在接下来的任何过程中执行出错了,都可以通过这句话将错误信息返回到前端,而不是直接抛出一个500服务器错误。
打个比方,下面的例子,name是要求unique的,也就是不能重复,假设我添加一个与之前名字相同的用户,那数据库肯定会报错,从而不会执行ctx.body这句话,直接服务器异常了。
var employee = new ctx.models.Employee({
name:name,
age:age,
salary:salary,
phone:phone,
})
let a = await employee.save();
ctx.body = a;
先说增加,增加在mongoose中有个save()方法,可以参照controllers/data.js文件中 POST /createEmployee
创建员工的方式。这里说一下增加,其他的异曲同工。使用await等待save()执行完成,避免完成前默认返回Not Found.然后执行完成之后返回执行结果,前端根据结果判断执行结果。如果执行过程中发生异常,那么就会被一开始设置的handler捕获到,从而返回错误信息,保证都是可以返回结果的,而不是500错误。
'POST /createEmployee': async (ctx, next) => {
var name = ctx.request.body.name || '';
var age = ctx.request.body.age || '';
var salary = ctx.request.body.salary || '';
var phone = ctx.request.body.phone || '';
var employee = new ctx.models.Employee({
name:name,
age:age,
salary:salary,
phone:phone,
})
let a = await employee.save();
ctx.body = a;
},
再说删除,参照controllers/data.js文件中DELETE /deleteEmployee
方法。
'DELETE /deleteEmployee': async (ctx, next) => {
let rst = await ctx.models.Employee.deleteOne({'name': ctx.request.query.name});
ctx.response.body = rst;
},
修改,参照同文件中PUT /updateEmployee
方法。
'PUT /updateEmployee': async (ctx, next) => {
var name = ctx.request.body.name || '';
var age = ctx.request.body.age || '';
var salary = ctx.request.body.salary || '';
var phone = ctx.request.body.phone || '';
let obj = {
name,
age,
salary,
phone
}
let rst = await ctx.models.Employee.updateOne({'name':ctx.request.query.name}, obj);
ctx.response.body = rst;
},
查询,参照同文件中GET /tabledata
方法,以及GET /users
方法,其中users提供了根据参数来查询的方式。可以通过url?name=xiaogang的方式来查询。
'GET /users': async (ctx, next) => {
var query = ctx.request.query; // if nothing to pass just return a {}
var rst = [];
if (query.name) {
rst = await ctx.models.User.find({userName: query.name});
}else {
rst = await ctx.models.User.find(); // if no name params,just query all users
}
ctx.response.body = {users: rst};
},
这里在data.js文件中,还有个GET /wormpic
,这个方法实现了通过node从网络抓取数据。
还有controllers/signin.js文件中,POST /zhece
方法的注释部分,他实现了Node发送邮件的功能。
有兴趣的可以了解一下。
文章写到这里就差不多了,如果大家有什么指导意见,欢迎留言,相互进步。