跟我一起学NodeJs之POST接口处理
NodeJs异步读取文件
前面我们介绍了使用NodeJS来写GET
请求代码,那么接下来我们将写POST
请求代码
在我们一开始模拟简单的POST
请求中,我们介绍过,POST
请求使用一种数据流的方式获取数据,这种方式是异步的,那么我们当我们需要写真正的接口时,首先要学习的一个内容就是nodejs异步读取文件
如果你熟练掌握JS的话,应该不难知道JS异步可以通过callback的形式来实现,但是callback存在回调地狱的问题,于是就有了Promise来解决这一问题,如果你不了解这些的话,那么你可能需要回炉再造了。
那我们直接上代码
为了模拟异步获取文件,我们需要建立下面这样的文件结构
—file
——a.json
——b.json
——c.json
—index.js
其中
//a.json
{
"next": "b.json",
"msg": "this is a "
}
//b.json
{
"next": "c.json",
"msg": "this is b "
}
//c.json
{
"next": null,
"msg": "this is c"
}
//通过这种文件名的指向,模拟文件之间的依赖关系
//index.js
const fs = require('fs')
const path = require('path')
//callback方式获取一个文件的内容
function getFileContent(fileName, callback) {
const fullFileName = path.resolve(__dirname, 'file', fileName)
fs.readFile(fullFileName, (err, data) => {
if (err) {
console.error(err)
return
}
callback(
JSON.parse(data.toString())
)
})
}
//测试 -->回调地狱
getFileContent('a.json', aData => {
console.log('aData', aData)
getFileContent(aData.next, bData => {
console.log('bData', bData)
getFileContent(bData.next, cData => {
console.log('cData', cData)
})
})
})
//用Promise获取文件内容
function getFileContent(fileName) {
const promise = new Promise((resolve, reject) => {
const fullFileName = path.resolve(__dirname, 'file', fileName)
fs.readFile(fullFileName, (err, data) => {
if (err) {
reject(err)
return
}
resolve(
JSON.parse(data.toString())
)
})
})
return promise
}
getFileContent('a.json').then(aData => {
console.log('aData',aData)
return getFileContent(aData.next)
}).then(bDate => {
console.log('bData', bDate)
return getFileContent(bDate.next)
}).then(cData => {
console.log('cData', cData)
})
- 其中的
fs
、path
、__dirname
都是NodeJS提供的原声方法,分别代表“文件操作”、“路径操作”、“获取当前路径”。我们可以参照官网,了解其具体用法,总之,我们运用这些自带功能的API实现了文件的读取 - 我们在上面代码中分别使用了callback和promise的形式来获取文件信息,在后面的代码中,我们将使用
promise
来处理文件, - 至于
async/awite
,我们将在koa2中引入,因为现在我们还处于学习阶段,我们将使用Promise来做异步获取文件。
处理POSTData
我们已经知道,postData是通过异步获取,上面我们也讲到了通过pormise的方式异步读取文件,那么接下来,我们将用Promise
的方式处理PostData。
//在这里定义其处理函数
const getPostData = req => {
const promise = new Promise((resolve, reject) => {
if (req.method !== 'POST') {
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
}
//在这使用,我们将更改之前的app.js文件,将路由的处理放到postData的处理函数中
getPostData(req).then(postData => {
req.body = postData
//处理blog路由
const blogData = handleBlogRouter(req, res)
if (blogData) {
res.end(
JSON.stringify(blogData)
)
return
}
//处理user路由
const userData = handleUserRouter(req, res)
if (userData) {
res.end(
JSON.stringify(userData)
)
return
}
//未命中路由返回404
res.writeHead(404, { "Content-type": "text/plain" })
res.write("404 Not Found\n")
res.end()
})
}
如上,我们就可以把postData取出来,放到request.body中。在使用的时候,就可以从这里取到了。对于一些其他情况,如,请求方式不是post或者内容返回格式不是json的情况,我们也不当做错误来处理,只是将一个空对象放在body中即可(反正我们也不会用到)。
上面我们讲到了如何获取PostDate,那么接下来我们就实现一个POST
接口了,既然数据已经能拿到,那么接口的实现其实和GET
接口都是一样的操作了,只不过我们需要从request.body
里面获取数据。
下面是实例代码
if (method === 'POST' && req.path === '/api/blog/new') {
const postData = req.body
const data = newBlog(postData)
return new SuccessModel(data)
}
OK,就是这么简单,接下来用你的POSTman测一下吧!
总结:到此为止,我们已经学会了将应用分层,并且针对不同的接口(路由),不同的请求方式开发不同的处理方式。当然了,对于一些其他的请求方式(PUT
、DELETE
...)也是同样的流程。接下来的事件,我们将学习数据存储,这将是服务端开发的重中之重。