上篇博客记录了《Node.js 从零开发web server博客项目》项目的初始化及初步的项目结构规划。
开篇将继续接着上篇中的项目内容,介绍返回内容的设计与解析postData。
对于接口返回的内容结构,我们通过一个创建一个resModel.js进行说明。新建model/resModel.js,
class BasicModel{
constructor(data, message){
if(typeof data === "string"){
this.data = data;
data = null;
message = null;
}
if(data){
this.data = data;
}
if(message){
this.message = message;
}
}
}
class SuccessModel extends BasicModel{
constructor(data,message){
super(data,message);
this.errorno = 0;
}
}
class ErrorModel extends BasicModel{
constructor(data,message){
super(data,message);
this.errorno = -1;
}
}
module.exports = {
SuccessModel,
ErrorModel
}
为返回的数据内容创建一个基类,包含data和message。返回成功及返回错误都继承这个基类。
我们将在router文件中使用,比如在获取博客列表接口中,我们使用方式如下:
if(method==="GET" && path==="/api/blog/list"){
// 获取参数
const keyword = req.query.keyword || '';
const author = req.query.author || '';
const listData = getList(keyword,author);
return new SuccessModel(listData,'success');
}
注意到,相比于上次博客中介绍的接口,我们新增一个获取博客列表的方法,getList,并传入关键字及作者作为参数。
接口中处理数据的方法,我们放在controller/blog.js中,在blog.js中专门处理与博客相关数据的处理。
const getList = (keyword, author) => {
return [{
id:1,
title:'标题1',
content:'内容',
createTime:12345678,
author:'张三'
}];
}
const getBlog = (id) => {
return {
id:1,
title:'标题1',
content:'内容',
createTime:12345678,
author:'张三'
};
}
const newBlog = (blogData)=>{
return {
id:3
}
}
const updateBlog = (id, blogData) => {
return true;
}
module.exports = {
getList,
getBlog,
newBlog,
updateBlog
};
上面贴出的代码描述了四个接口的处理过程,到目前为止,我们的接口仍然未与数据库进行交互,都是直接返回写死的内容。
截止目前为止,我们的项目结构如下图所示。
上面我们举了一个get请求的接口--获取博客列表,参数都是放在链接上,对于get请求,我们项目通过querystring解析search的参数列表,放在req.query中。
对于post请求,我们需要等待post数据接收完毕,放在req.body中。这样我们就把入参比较同意地放在req的各自参数中。第一篇博客有提到post的数据结合req.on('data',(data)=>{})与req.on('end',()=>{})获取,而这个过程是异步的,所以我们用Promise对这个过程进行处理。
const getPostData = (req) => {
const promise = new Promise(
(resolve,reject) => {
if(req.method === "GET"){
resolve({});
return;
}
if(req.headers['content-type']!=='application/json'){
resolve({});
return;
}
let postData = '';
req.on('data',(chunk)=>{
postData += chunk.toString();
});
req.on('end',()=>{
if(!postData) {
resolve({});
return;
}
resolve(
JSON.parse(postData)
);
})
}
);
return promise;
}
getPostData将对req中的post内容进行处理,并返回。由于项目限制传参必须是json格式,所以非json内容postdata返回为空对象。
对post数据的处理,我们也是放在app.js中进行的。处理完成之后,再调用相应的路由处理方法。
getPostData(req).then(
(postData) => {
req.body = postData;
const userLogin = userRouterHandler(req, res);
if(userLogin){
res.end(JSON.stringify(userLogin));
return;
}
const blogData = blogRouterHandler(req, res);
if(blogData){
res.end(JSON.stringify(blogData));
return;
}
res.writeHead(404, {"Content-type":"text/plain"});
res.write("404 Not Found");
res.end();
}
)
到目前为止,项目已经分了这么几个层次
1、www.js,项目入口文件,主要是创建httpServer,并监听端口
2、app.js,serverHandler,主要对req,res进行处理,获取path用于api匹配,获取query参数,获取post数据,并调用router中的相关处理方法
3、router部分,主要根据不同模块处理不同的api入口,根据req.path进行匹配分发,调用api的实现方法。获取查询参数与post数据,并将这些作为controller层的各个业务处理函数的入参。
4、controller部分,这部分主要实现各个api对应的业务逻辑实现,输入为router中的获取的参数。
5、model层,公用的model,如返回数据模型,含有data,message,errorno等信息
到目前为止,controller中的业务实现逻辑并未涉及到数据库的内容,目前还是静态数据,接下来将介绍数据库连接,数据库操作等内容。