/** * Created by Sorrow.X on 2017/10/25. */ const http = require('http'); const url = require('url'); const net = require('net'); // 單例 let httpServer = (function() { let port = 8888; let server = null; let serverStartedCb = null; let noop = function() {}; // 初始化http服務器 let initServer = function({serverStarted}) { serverStartedCb = serverStarted || noop; startServer(increPort()); }; // 關閉服務器 let closeServer = function() { if (server) { server.close(); server = null; }; }; // 端口增加 function increPort() { return ++port; }; // 格式化url function format(str) { let obj = {}; str = str.substr(str.indexOf('?') + 1); let arr = str.split('&'); arr.forEach(function(item) { let a = item.split('='); obj[a[0]] = a[1]; }); return obj; }; // 啟動服務器 function _server(port) { server = new http.Server(); server.on('request',(req, res)=>{ let content = { Code: -1, Body: { message: 'request url error' } }; if (req.url.indexOf('ball/queryUrl') > 0) { let obj = format(req.url); if (obj.type == '1') { content.Code = 0; content.Body = { message: 'hi' }; }; }; //設置應答頭信息 res.writeHead(200,{'Content-Type':'text/plain'}); res.write(JSON.stringify(content)); res.end(); }); server.on('listening', () => { console.log("server listening, 端口號和url為: ", `localhost:${port}`); serverStartedCb(null); }); server.on('connection', () => { console.log("server connection..."); }); server.on('close', () => { console.log('server close...'); }); server.on('error', (err) => { server.close(); server = null; serverStartedCb(new Error(err)); console.log('server error: ', err); }); server.listen(port); }; // 檢測port是否被占用 function probe(port, callback) { let server = net.createServer().listen(port); let calledOnce = false; let timeoutRef = setTimeout(function () { calledOnce = true; callback(false, port); }, 2000) timeoutRef.unref(); // 取消定時器 let connected = false; server.on('listening', function() { clearTimeout(timeoutRef); if (server) server.close(); if (!calledOnce) { calledOnce = true; callback(true, port); // true 表示未被占用 }; }); server.on('error', function(err) { clearTimeout(timeoutRef); let result = true; if (err.code === 'EADDRINUSE') result = false; // 占用 if (!calledOnce) { calledOnce = true; callback(result, port); // false 表示占用 }; }); }; function startServer(port){ probe(port, function(bool, port) { // 端口被占用: bool 返回false; port:傳入的端口號 if (bool === true) { // 端口號未被占用 _server(port); } else { // 已占用 closeServer(); _server(increPort()); }; }); }; let single; return function() { return single ? single : (single = {initServer, closeServer}); }; }()); // module.exports = httpServer(); // test var ballServer = httpServer(); var ballServer2 = httpServer(); console.log(ballServer === ballServer2); // 測試是否同一個對象 ballServer.initServer({ serverStarted: function(err) { if (!err) { console.log('服務已啟動: '); }; } }); // ballServer.closeServer();