简单启动一个服务器
var http = require('http')
var server = http.creatServer(); //证明http变量是一个对象,对象里有一个名为creatServer的方法,这个方法的返回值赋值给server
server.listen(8888)//证明server也是一个对象。有一个listen的方法
这段代码只会启动一个侦听8888端口的服务器,它不做任何别的事情,甚至连请求都不会应答。
函数参数仍是函数
function say(word) {
console.log(word)
}
function execute(someFunction, value) {
someFunction(value)
}
execute(say, 'hellow')
我们把 say 函数作为execute函数的第一个变量进行了传递。这里传递的不是 say 的返回值,而是 say 本身!所以我们的creatServer的参数也可以是一个函数
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
不过我们为什么要用这种方式(传递函数参数的方式)?因为node是基于事件驱动的回调
基于事件驱动的回调
回调,js中解决异步的最基本方法。node.js也是运行的js所以就是单线程的。就像我们使用http.createServer的目的不是为了简单的监听一个端口,而是可以处理些什么事情,就像这个端口上的http请求。请求随时可能会来到,但我们的node是单线程的。不像php其他脚本,来一个请求我就开一个线程来运行代码。这时候就要用到回调了,解决异步问题。我们给某个方法传递了一个函数,这个方法在有相应事件发生时调用这个函数来进行 回调 。我们不知道请求什么时候会来到。但是每个来到的请求我们都有对应的函数来处理他,至于怎么处理什么时候处理,就不用我们关心了。那异步的话是不是还是每个请求完成后的回调到队列池里需要等待呢?是的。需要等待,意思就是可以同时接受上万个请求,但每个请求完成的回调还是要排队进行。但至少每个请求都是不阻塞的。java这种多线程的,最多多开几个线程,每个线程上的请求还都是阻塞的。node处理高并发 和阻塞与非阻塞
为了不使一个js文件内容过多,我们要进行模块化,对于上面的代码怎么进行模块的输出引用呢?
var http = require("http");
function start() {
function onRequest(request, response) {
console.log("Request received.");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
别处引用就可以这样子写
var server = require("./server");
server.start();
现在我们需要不同请求来我们起得服务可以返回不同的东西,这不就是路由的需求吗。我们先写一个router.js来存放我们的路由函数
function route(pathname){
console.log("About to route a request for " + pathname);
}
exports.route = route
现在我们把route和起得服务我们叫server.js整合到一块
把route函数以参数的形式加到server.js中 文档说是要依赖注入???。
var http = require("http");
var url = require("url");
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
route(pathname);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
同时,我们会相应扩展index.js,使得路由函数可以被注入到服务器中:
var server = require("./server");
var router = require("./router");
server.start(router.route);
路由,顾名思义,是指我们要针对不同的URL有不同的处理方式。例如处理/start的“业务逻辑”就应该和处理/upload的不同。路由只是把不同的URl指向不同的模块去处理。现在呢,我们来写真正的路由执行模块。例如叫做requestHandlers模块。
function start() {
console.log("Request handler 'start' was called.");
}
function upload() {
console.log("Request handler 'upload' was called.");
}
exports.start = start;
exports.upload = upload;
这里的start和upload通过什么方式传递到route函数里呢。为了减少耦合,让路由函数的复用性增加。路由函数内就不能写死。所以我们还是通过依赖注入(这里简单的理解为传参?)的方式来传递。但是我们的route函数都是通过从server.js传参。这样一个一个传递start和upload的话。很麻烦。我们当然不想每次有一个新的URL或请求处理程序时,都要为了在路由里完成请求到处理程序的映射而反复折腾。除此之外,在路由里有一大堆if request == x then call handler y也使得系统丑陋不堪。
仔细想想,有一大堆东西,每个都要映射到一个字符串(就是请求的URL)上?似乎关联数组(associative array)能完美胜任。所以我们想到了对象
所以我们的index.js可以这么写
var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");
var handle = {}
handle["/"] = requestHandlers.start;
handle["/start"] = requestHandlers.start;
handle["/upload"] = requestHandlers.upload;
server.start(router.route, handle);
server.js中我们用route函数把handle继续传下去。
route(handle, pathname);
于是我们的route模块
function route(handle, pathname) {
console.log("About to route a request for " + pathname);
if (typeof handle[pathname] === 'function') {
handle[pathname]();
} else {
console.log("No request handler found for " + pathname);
}
}
exports.route = route;
参考 node.js入门