前端结构如下:
点击'登录-post'按钮将用户名和密码返回给后端,后端接收到后再返回数据给前端
在server.js中将use()方法和serverStart()方法暴露出去,use()方法用于不断将新的接口合并到已有接口中。
const http = require('http');
const router = {};
function use(obj) {
Object.assign(router, obj)
}
const serverStart = () => {
http.createServer((req, res) => {
const curUrl = new URL(req.url, 'http://127.0.0.1:3000');
// console.log(curUrl.pathname);
// router(curUrl.pathname, res)
try {
router[curUrl.pathname](req, res, (data) => {
res.write(data)
res.end()
})
} catch (error) {
router['/404'](req, res)
}
}).listen(3000, () => {
console.log('server start');
})
}
exports.serverStart = serverStart
exports.use = use
使用use()方法:
index.js
const server = require('./server.js');
const route = require('./router.js');
const api = require('./api.js');
server.use(route)
server.use(api)
server.serverStart()
我在使用POST请求时遇到了一个问题,前端点击按钮将用户名和密码传给本地自己写的'/api/loginpost'接口:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
用户名:<input type="text" id="userName">
</div>
<div>
密码:<input type="text" id="password">
</div>
<div>
<button id="login">登录-get</button>
<button id="login-post">登录-post</button>
</div>
<script>
let dom = {
getUserName: document.querySelector('#userName'),
getPassword: document.querySelector('#password'),
getLogin: document.querySelector('#login'),
getLoginPost: document.querySelector('#login-post')
}
dom.getLogin.onclick = function () {
fetch(`/api/login?username=${dom.getUserName.value}&password=${dom.getPassword.value}`)
.then((res) => { return res.text(); })
.then((res) => { console.log(res); });
}
dom.getLoginPost.onclick = function () {
fetch(`/api/loginpost`, {
method: 'POST',
body: JSON.stringify({
userName: dom.getUserName.value,
password: dom.getPassword.value
}),
headers: {
'Content-Type': 'application/json'
}
}).then((res) => { return res.text(); })
.then((res) => { console.log(res); });
}
</script>
</body>
</html>
在'/api/loginpost'接口中接收数据并处理返回数据给前端:
'/api/loginpost': (req, res, cb) => {
let post = '';
req.on('data', (chunk) => {
post += chunk;
})
req.on('end', () => {
post = JSON.parse(post);
console.log(post);
if (post.userName === 'fanfan' && post.password === '666') {
render(res, `{'fanfan': 666}`, cb)
} else {
render(res, `{'fanfan': 0}`, cb)
}
})
}
const render = (res, data, cb, type = 'application/json') => {
res.writeHead(200, {
'Content-Type': type + `;charset=utf-8`
})
cb(data)
}
最开始的时候在req上监听on事件一点一点接收数据,数据收集完毕时调用render()方法处理数据并返回给前端,然后在server.js中的服务器方法中执行res.end()响应。
这里有一个问题,由于在接口中监听的on事件是异步执行的,在server.js中调用接口函数时,数据还没收集完,render()方法还没有渲染完数据返回给前端,服务器就过早执行end响应了,导致页面上后端返回的是空白。
在这里我想到了使用回调函数来解决这个问题
具体做法:
在服务器调用接口方法时传入一个回调函数
在接口方法中接收,数据收集完毕后执行render()方法将这个回调函数传进去
在render()方法中接收回调函数
等数据收集完毕并处理好后再执行回调函数,在回调函数里面执行end响应就能避免end响应过早的问题 ,前端就能正常拿到后端返回的数据