node.js
第一个应用 Hello world
新建一个 111.js文件
在命令行中 输入 node 111.js
稍微复杂的应用,技术要求:
- 用户可以通过浏览器使用我们的应用。
- 当用户请求http://domain/start时,可以看到一个欢迎页面,页面上有一个文件上传的表单。
- 用户可以选择一个图片并提交表单,随后文件将被上传到http://domain/upload,该页面完成上传后会把图片显示在页面上。
应用不同的模块分析
- 我们需要提供Web页面,因此需要一个HTTP服务器
- 对于不同的请求,根据请求的URL,我们的服务器需要给予不同的响应,因此我们需要一个路由,用于把请求对应到请求处理程序(request handler)
- 当请求被服务器接收并通过路由传递之后,需要可以对其进行处理,因此我们需要最终的请求处理程序
- 路由还应该能处理POST数据,并且把数据封装成更友好的格式传递给请求处理入程序,因此需要请求数据处理功能
- 我们不仅仅要处理URL对应的请求,还要把内容显示出来,这意味着我们需要一些视图逻辑供请求处理程序使用,以便将内容发送给用户的浏览器
- 最后,用户需要上传图片,所以我们需要上传处理功能来处理这方面的细节
使用Node.js时,我们不仅仅在实现一个应用,同时还实现了整个HTTP服务器。事实上,我们的Web应用以及对应的Web服务器基本上是一样的。
构建应用的模块
一个基础的HTTP服务器
//服务器模块
//请求(require) Node.js 自带的http模块,并且把赋值给http变量
var http = require('http');
// 调用http模块提供的函数: createServer,
// 这个函数会返回一个对象,对象有一个listen 的方法,这个方法有一个参数,制定HTTP 服务器监听的端口号
http.createServer(function(request, response) {
response.writeHead(200, {
"Content-Type": "text/plain"
});
response.write('Hello world');
response.end();
}).listen(8888)
// 基于事件驱动的回调
// 不过这是Node.js原生的工作方式。它是事件驱动的,这也是它为什么这么快的原因
当我们使用http.createServer方法的时候,我们当然不只是想要一个侦听某个端口的服务器,我们还想要它在服务器收到一个HTTP请求的时候做点什么。这是异步的:请求任何时候都可能到达,但是我们的服务器却跑在一个单进程中。
解决方法
php中
写PHP应用的时候,我们一点也不为此担心:任何时候当有请求进入的时候,网页服务器(通常是Apache)就为这一请求新建一个进程,并且开始从头到尾执行相应的PHP脚本。
在node.js中
在我们的Node.js程序中,当一个新的请求到达8888端口的时候,我们怎么控制流程呢?
Node.js/JavaScript的事件驱动设计能够真正帮上忙的地方了
我们创建了服务器,并且向创建它的方法传递了一个函数。无论何时我们的服务器收到一个请求,这个函数就会被调用。 我们不知道这件事情什么时候会发生,但是我们现在有了一个处理请求的地方:它就是我们传递过去的那个函数。至于它是被预先定义的函数还是匿名函数,就无关紧要了
这个就是我们所谓的 ----- 回调函数
我们给某个方法传递了一个函数,这个方法在有相应事件发生时调用这个函数来进行 回调 。
我们怎么证明,在创建完服务器之后,即使没有HTTP请求进来、我们的回调函数也没有被调用的情况下,我们的代码还继续有效呢?我们试试这个:
var http = require("http");
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.");
注意:在 onRequest (我们的回调函数)触发的地方,我用 console.log 输出了一段文本。在HTTP服务器开始工作之后,也输出一段文本。
当我们与往常一样,运行它node server.js时,它会马上在命令行上输出“Server has started.”。当我们向服务器发出请求(在浏览器访问http://localhost:8888/ ),“Request received.”这条消息就会在命令行中出现。
这就是事件驱动的异步服务器端JavaScript和它的回调啦!
(请注意,当我们在服务器访问网页时,我们的服务器可能会输出两次“Request received.”。那是因为大部分浏览器都会在你访问 http://localhost:8888/ 时尝试读取 http://localhost:8888/favicon.ico )
服务器是如何处理请求的
回调函数 onRequest() 的主体部分
当回调启动,我们的 onRequest() 函数被触发的时候,有两个参数被传入: request 和 response 。
它们是对象,你可以使用它们的方法来处理HTTP请求的细节,并且响应请求(比如向发出请求的浏览器发回一些东西)。
所以我们的代码就是:当收到请求时,使用 response.writeHead()函数发送一个HTTP状态200和HTTP头的内容类型(content-type),使用 response.write() 函数在HTTP相应主体中发送文本“Hello World"。
最后,我们调用 response.end() 完成响应。
服务端的模块放在哪里
模块化 的
index.js
var server = require("./server");
server.start()
在server.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;