了解nodejs
非阻塞
想象一下我们现在已经有了一个多线程服务器,运行于Ruby on rails环境。我们需要它读取文件并且发送给请求这个文件的浏览器。首先要知道的是Ruby并不会直接读取文件,而是通知文件系统去读取指定文件并返回它内容。顾名思义,文件系统就是计算机上一个专门用来存取文件的程序。
Ruby在向文件系统发出通知后会一直等待它完成读取文件的操作,而不是转头去处理其他任务。当文件系统处理任务完成后,Ruby才会重新启动去收集文件内容并且发送给浏览器。
这种方式很显然会造成阻塞的情况,而NodeJS的诞生就是为了解决这个痛点。如果我们使用Node来向文件系统发出通知,在文件系统去读取文件的这段时间里,Node会去处理其他请求。而读取文件的任务完成后,文件系统会通知Node去读取资源然后将它返回给浏览器。事实上,这里的内部实现都是依赖于Node的事件循环。
Node的核心就是JavaScript和事件循环。
事件驱动

事件循环就是一个等待事件然后在需要事件发生时去触发它们的程序。此外还有一点很重要,就是Node和JavaScript一样都是单线程的。
优势:
超强的高并发能力
Nodejs不为每个客户连接创建一个新线程,仅仅使用一个线程。当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。
实现高性能服务器
在JavaScript脚本语言中,只具非常有限的二进制数据的处理能力,而Node.js提供的Buffer类则提供了丰富的二进制数据处理能力。另外,在V8 JavaScript引擎内部使用一种全新的编译技术。这意味着开发者编写的高端的 JavaScript 脚本代码与开发者编写的低端的C语言具有非常相近的执行效率,这也是Node.js服务器可以提供的一个重要特性。
用NodeJS写一个web应用
用NodeJS写一个web应用相当于编写事件回调。让我们来看看下面的例子:
- 新建并进入一个文件夹
- 执行
npm init命令,一直回车直到你在文件夹根目录下创建了一个package.json文件。 -
新建一个名为server.js的文件,复制并粘贴下面的代码:
首先,我们引入了http模块。这个模块提供了处理http操作的接口,我们调用createServer()方法来创建一个服务器。
之后,我们为request事件绑定了一个事件回调,传递给on方法的第二个参数。这个回调函数有2个参数对象,request代表接收到的请求,response代表响应的数据。
//server.js
const http = require('http'),
server = http.createServer();
server.on('request',(request,response)=>{
response.writeHead(200,{'Content-Type':'text/plain'});
response.write('Hello world');
response.end();
});
server.listen(3000,()=>{
console.log('Node server created at port 3000');
});
4.在命令行中,输入node server.js,你会看到下面的输出:
node server.js
//Node server started at port 3000
打开浏览器并且进入localhost:3000,你应该能够看到一个Hello world信息。
NodeJS路由
一个服务器会存储大量的文件。当浏览器发送请求时,会告知服务器他们需要的文件,而服务器会将相应的文件返回给客户端。这就叫做路由。
在NodeJS中,我们需要手动定义自己的路由。这并不麻烦,看看下面这个基本的例子:
//server.js
const http = require('http'),
url = require('url'),
makeServer = function (request,response){
let path = url.parse(request.url).pathname;
console.log(path);
if(path === '/'){
response.writeHead(200,{'Content-Type':'text/plain'});
response.write('Hello world');
}
else if(path === '/about'){
response.writeHead(200,{'Content-Type':'text/plain'});
response.write('About page');
}
else if(path === '/blog'){
response.writeHead(200,{'Content-Type':'text/plain'});
response.write('Blog page');
}
else{
response.writeHead(404,{'Content-Type':'text/plain'});
response.write('Error page');
}
response.end();
},
server = http.createServer(makeServer);
server.listen(3000,()=>{
console.log('Node server created at port 3000');
});
粘贴这段代码,输入node server.js命令来运行。在浏览器中打开localhost:3000和localhost:3000/abou,然后在试试打开localhost:3000/somethingelse,是不是跳转到了我们的错误页面?
虽然这样满足了我们启动服务器的基本要求,但是要为服务器上每一个网页都写一遍代码实在是太疯狂了。事实上没有人会这么做,这个例子只是让你了解路由是怎么工作的。
如果你有注意到,我们引入了url这个模块,它能让我们处理url更加方便。
使用Express进行路由
你一定听说过Express,这是一个用来构建web应用以及API的NodeJS框架,它也可以用来编写NodeJS应用。接着往下看,你会明白为什么我说它让一切变得更简单。
在你的终端或是命令行中,进入电脑的根目录,输入npm install express --save来安装Express模块包。要在项目中使用Express,我们需要引入它。
const express = require('express');
现在,让我们用express进行基本的路由。
//server.js
const express = require('express'),
server = express();
server.set('port', process.env.PORT || 3000);
//Basic routes
server.get('/', (request,response)=>{
response.send('Home page');
});
server.get('/about',(request,response)=>{
response.send('About page');
});
//Express error handling middleware
server.use((request,response)=>{
response.type('text/plain');
response.status(505);
response.send('Error page');
});
//Binding to a port
server.listen(3000, ()=>{
console.log('Express server started at port 3000');
});
浙公网安备 33010602011771号