如需转载请注明来源与作者
上一次,手写了一个静态服务器。这次我们想更进一步:返回给前端ajax数据。注意:这里只是一个演示,所以所有ajax传入服务器的数据,我不会经过处理直接返回
Tips :
fs.readFile(url,'utf8',(error,data)=>{
response.end(data);
})
上次使用的是utf-8
编码格式来读取文件,但是这样设置遇到返回图片就会报错。所以,我们可以删除utf8
这个字段,这样才能成功返回图片。
-
预处理:
- 首先文件夹的服务器文件处理也就是
APP
文件夹。应该进行进一步的抽离。 - 使用
Promise
作连接。
这样做能让模块之间相互独立又相互连接,使代码更好维护
接着我们把APP(APP/index.js)的枢纽进行整合:
let path = require('path')
let fs = require('fs')
let staticServer = require('./static-server');
class APP {
initSever() {
return (request, response) => {
let {url} = request;
staticServer(url).then((data)=>{
//这里staticServer返回的是一个promise
response.writeHead(200,'resolve ok',{'X-powered-by': 'Node.js'})
//标记一下返回头
response.end(data);
})
}
}
}
module.exports = APP
静态服务器(APP/static-server/index.js)的处理:
let fs = require('fs');
let path = require('path');
//对url进行处理让它能够定位到public下面的资源
let getPath = (url) => {
let urlHeader = './public'
return path.resolve(process.cwd(), urlHeader + url)
}
module.exports = (url) => {
return new Promise((resolve, reject) => {
if (url === '/') url = '/index.html';
url = getPath(url)
fs.readFile(url, (error, data) => {
//如果你不使用Promise的话,你可以使用fs,readFileSync进行同步的处理
resolve(data)
})
})
}
在前端代码引入jq与js,写点ajax
$.get({
url : 'user.action', //给每个ajax的请求后缀添加'.action'以作标识
dataType : 'json'
}).done(function(data){
console.log(data) //在这里我们直接打出数据
})
-
get方法的处理
api-server
let msgMap = {
'/user.action' : {
pet : 'dog',
color : 'white'
}
}
let data ='';
module.exports= (req)=>{
let {url} = req; // 这里先传req,接下来处理post会用到
data = msgMap[url]; //判断该url在映射表里面是否有对应的信息
return Promise.resolve(JSON.stringify(data))
//必须转换成字符串,否则response.end的第一个参数必须是字符串或者buffer
}
//上述代码运行成功后console打出的应该是一个对象。
APP/index.js
的修改:
class APP {
initSever() {
return (request, response) => {
let {url} = request;
apiServer(request).then((val) => {
//一个url进入服务器先在apiServer里面进行一个判断,
//返回出来的值如果是一个undefined就走静态资源路线
//否则就是ajax请求,直接返回给前端。
if (val) {
return val;
} else {
return staticServer(url)
}
})
.then((data) => {
//这里是用来把数据返回给前端的地方,在这一块主要是处理返回头。
response.writeHead(200, 'resolve ok', {
'X-powered-by': 'Node.js'
})
response.end(data);
})
}
}
}
结果:
-
post方法的处理
- 由于post比较复杂在这里先讲一下思路
post的处理比get的处理要烦琐得多。
post请求,我们往往是要传递数据给服务器。前端返回给后端服务器的形式是用stream
的形式,所以我们可以在request对象上获取前端返回的数据。
返回数据的处理:由于中文在stream传输的过程是以buffer形式,所以会造成字符串丢失,所以我们需要使用Buffer.concat
进行字符的拼接。
-
public/js/index.js
添加:
$.ajax({
method: 'POST',
url : '/getMsg.action',
data : JSON.stringify({ //注意这里应该转成字符串否则传到服务器会变成car=BMW&msg=hello world
car : 'BMW',
msg : 'hello world'
}),
dataType:'json'
}).done(function(data){
console.log(JSON.parse(data)) //在这里我们直接打出数据
})
- ·api-server/index.js·
let msgMap = {
'/user.action': {
pet: 'dog',
color: 'white'
}
}
let data = '';
let info = [];
module.exports = (req) => {
let {url} = req;
if (req.method.toLowerCase() === 'get') { //这一块不多说,处理get请求
data = msgMap[url];
return Promise.resolve(JSON.stringify(data))
} else {
return new Promise((resolve, reject) => {
req.on('data', (chunk) => {
//on类似于jquery添加事件,监听data是否传入数据,该方法在stream对象上
info.push(chunk)//为什么用数组,为了防止中文数据丢失所以我们把每一个buffer用数组存起来
//你也可以直接使用字符串拼接,如:info+=chunk;这样写相当于:info=info.toString() + chunk.toString()
}).on('end', () => {
info = Buffer.concat(info).toString(); // Buffer.concat用来拼接所有的buffer
//在这里你可以处理你想要的数据 doSomething(info)
resolve(JSON.stringify(info));//这里我只是把前端的数据拿过来没有做任何的改动直接返回
})
})
}
}
-
APP/index.js
不用特殊处理跟之前保持一致就好。