網友 bottle_ 供應搭建一個簡樸當地服務器的思緒為下:
- 我們須要一個 HTTP 服務器
- 關於差別的要求,依據要求的 URL,我們的服務器須要賦予差別的相應,因而我們須要一個路由,用於把要求對應到要求處置懲罰順序(request handler)
- 當要求被服務器吸收並經由過程路由通報今後,須要能夠對其舉行處置懲罰,因而我們須要終究的要求處置懲罰順序
- 我們須要從 HTML 文件里提取數據以及展現服務器傳入的數據,因而須要將 HTML 和服務器結合起來
index.js
援用模塊
const fs = require('fs'); // 體系文件及目次舉行讀寫操縱
const http = require('http'); // 封裝了高效的 HTTP 服務器和 HTTP 客戶端
const url = require('url'); // URL 處置懲罰
路由
/**
* 路由
* @param {Function} handle 要求處置懲罰順序
* @param {String} pathname 途徑
* @param {Object} response 相應數據
* @param {Object} postData 要求參數
*/
function route(handle, pathname, response, postData) {
if (typeof handle[pathname] === 'function') {
handle[pathname](response, postData);
} else {
response.writeHead(404, { 'Content-Type': 'text/plain' });
response.write('404 Not Found');
response.end();
}
}
服務器
/**
* 服務器
* @param {Function} route 路由
* @param {Function} handle 要求處置懲罰順序
*/
function start(route, handle) {
function onRequest(request, response) {
const pathname = url.parse(request.url).pathname;
let postData = '';
switch (request.method) {
case 'GET':
postData += url.parse(request.url).query;
request.setEncoding('utf8');
route(handle, pathname, response, postData);
break;
case 'POST':
request.addListener('data', function (postDateChunk) {
postData += postDateChunk;
});
request.addListener('end', function () {
route(handle, pathname, response, postData);
});
break;
};
}
http.createServer(onRequest).listen(8080);
console.log('Server has started');
}
要求處置懲罰順序
// 要求處置懲罰順序
const handle = {
// index 接口
'/public/index.html': function (response, postData) {
const pathname = __dirname + '/public/index.html';
fs.readFile(pathname, function (err, data) {
response.end(data);
});
},
// download 接口
'/download': function (response, postData) {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.write(JSON.stringify({
code: 200,
data: {
'time': new Date().toLocaleString("en-US")
}
}));
response.end();
},
// upload 接口
'/upload': function (response, postData) {
response.writeHead(200, { 'Content-Type': 'text/html' });
response.write('You have sent: ' + JSON.parse(postData).value);
response.end();
}
};
啟動服務器
// 啟動服務器 = 路由處置懲罰 + 接口處置懲罰
start(route, handle);
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text" name="input">
<button value="submit" name="submit">submit</button>
<p></p>
<!-- submit demo -->
<script>
const btn = document.querySelector('button');
btn.addEventListener('click', function () {
const value = document.querySelector('input').value;
ajax(value);
}, true);
function ajax(value) {
const xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp = new XMLHttpRequest();
} else {
xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
}
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
document.querySelector('p').innerHTML = xmlhttp.responseText;
}
}
xmlhttp.open('POST', '/upload', true);
xmlhttp.send(JSON.stringify({
value: value
}));
// xmlhttp.open('GET', '/upload?value='+value, true);
// xmlhttp.send();
}
</script>
</body>
</html>
關於 GET 和 POST 體式格局的要求參數
GET 的要求參數是以查詢參數情勢放在 URL 背面的,服務器能夠從 URL 上獵取參數:url.parse(request.url).query
。
POST 的要求參數則須要作為 xhr.send()
的參數並轉換為字符串來通報,本文運用 JSON.stringify()
來轉換,再在服務器端用 JSON.parse()
轉換。
服務器端在相應兩種要求體式格局時,相應數據格式參考官方文檔。
關於服務器相應頭中的 Content-Type
平常網站的做法是:當返回 HTML 頁面時為 text/html,當運用 JSONP 時為 text/javascript,當運用 CORS 時為 application/json。
關於 Node.js 熱布置
Node.js 啟動服務器時是將劇本放入內存,今後都邑直接接見內存,防止反覆載入。這類設想雖然有利於進步機能,卻不利於開闢調試,致使修正 Node.js 代碼后須要手動停止歷程並重啟才會見效。
網友 會奔馳的胖子 提出計劃:
你只須要在修正文件后保留,它就可以自動替你宣布,這就是所謂的熱布置。
supervisor 就是一個 Node.js 的開源熱布置東西:
npm i supervisor -g
supervisor server.js
該網友還提到另一個開源熱布置東西 hotcode,但經測試 hotcode 若運用 express 4.x 則會報錯,由於 hotcode 運用的 express.createServer() 已被燒毀。
參考:
進修筆記:用Nodejs搭建一個簡樸的當地服務器
NodeJS”熱布置“代碼,完成動態調試(hotnode,能夠完成熱更新)