Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.html
Node.js是一个基于Google Chrome的V8引擎的JavaScript运行环境,它容许使用JavaScript语言编写服务器端代码。Node.js具备事件驱动和I/O非阻塞两大特色,轻量而高效。node
官网地址webpack
从官网下载最新版本的Node.js,直接安装。安装时选择所有组件,并添加到环境变量Path中。web
运行命令:node -v
查看是否安装成功。算法
运行命令:node
进入到node.js的交互环境,能够输入任意JavaScript语句,并查看运行结果。数据库
运行命令:node <*.js>
直接执行js文件里的内容。express
运行命令:node --use_strict <*.js>
为js文件开启严格模式。npm
安装Node.js的时候,会自动安装包管理工具npm。后端
运行命令:npm -v
查看npm的版本。api
命令行模式会一次性执行js文件,中间没有交互;交互模式则是每一行单独执行,能够进行交互。
若是不想使用集成的IDE,可使用VS Code编辑器进行Node.js的开发和调试。具体操做和配置能够参照VS Code的官网教程。
Node.js Applications with VS Code
在Node.js环境中,一个js文件就称之为一个模块。使用模块提升了代码的可维护性以及可重用性,还避免了函数名和变量名冲突。
当在模块中定义一个对象(对象、函数、数组等)时,能够输出这个对象以供其余模块使用:
module.exports = object_name;
其余模块要想使用这个对象,能够在模块中引入该对象:
var variable_name = require('/path/to/the/module/module_name');
Tips:若是不指定路径,Node会按照内置模块、全局模块、当前模块的顺序进行查找。
在浏览器中,JavaScript有一个全局对象window;而在Node.js环境中,也有一个全局对象global。因为JavaScript代码既能在浏览器执行,也能在Node环境下执行,能够经过全局对象名称来判断JavaScript代码是在哪一个环境下执行的。
process也是Node.js提供的一个对象,表示当前Node.js进程,进程自己的事件由process来处理。
fs模块是文件系统模块,负责文件的读写操做,提供了同步和异步两种方法。大部分做为服务端的代码,必须使用异步代码。可是在服务器启动时读取配置文件,或结束时写入状态等操做,由于这些代码只执行一次,因此可使用同步方法。
读文本文件:
var fs = require('fs'); fs.readFile('input.txt', 'utf-8', function (err, data) { if (err) { console.log(err); } else { console.log(data); } });
其中,readFile函数的第一个参数是文件名,第二个参数是文件编码,第三个参数是一个回调函数。回调函数的第一个参数表明错误信息,第二个参数表明返回结果。
读二进制文件:
var fs = require('fs'); fs.readFile('input.png', function (err, data) { if (err) { console.log(err); } else { console.log(data); console.log(data.length + ' bytes'); } });
其中,不须要文件编码,而且回调函数的data参数将返回一个Buffer对象。Buffer对象是一个包含零个或任意个字节的数组。
写文件:
var fs = require('fs'); var data = 'Hello world'; fs.writeFile('output.txt', data, function (err) { if (err) { console.log(err); } else { console.log('success'); } });
其中,writeFile函数的第一个参数是文件名,第二个参数是要写入的数据,第三个参数是回调函数。
读取文件的相关信息:
fs.stat('input.txt', function (err, stat) { ... });
stream是一个只能在服务端使用的模块,用来支持流数据结构,流中的数据是有序的。流是一个对象,使用时只需关注流的事件便可。data事件表示流的数据能够读取,end事件表示流没有数据能够读取,error事件表示出现错误。
读文件:
var fs = require('fs'); var rs = fs.createReadStream('input.txt', 'utf-8'); rs.on('data', function (chunk) { console.log('DATA:'); console.log(chunk); }); rs.on('end', function () { console.log('END'); }); rs.on('error', function (err) { console.log('ERROR: ' + err); });
写文件:
var fs = require('fs'); var ws1 = fs.createWriteStream('output1.txt', 'utf-8'); ws1.write('使用Stream写入文本数据...\n'); ws1.write('END.'); ws1.end(); var ws2 = fs.createWriteStream('output2.txt'); ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8')); ws2.write(new Buffer('END.', 'utf-8')); ws2.end();
可使用管道操做pipe将读取流和写入流串联起来:
var fs = require('fs'); var rs = fs.createReadStream('input.txt'); var ws = fs.createWriteStream('output.txt'); rs.pipe(ws);
默认状况下,当读取流的数据读取完毕,会触发end事件,并自动关闭写入流。若是不想关闭,须要传递额外的参数。
readable.pipe(writable, { end: false });
http模块是web应用最经常使用的一个模块,提供了request和response对象。request对象封装HTTP请求,调用request对象的属性和方法,能够获取HTTP请求的全部信息;response对象封装HTTP响应,调用response对象的方法,能够把HTTP响应返回给浏览器。
var http = require('http'); var server = http.createServer(function (request, response) { // 获取HTTP请求的method和url console.log(request.method + ':' + request.url); // 将HTTP响应的内容写入response response.writeHead(200, {'Content-Type': 'text/html'}); response.end('<h1>Hello world!</h1>'); }); // 监听8080端口 server.listen(8080);
url模块能够用来将URL字符串解析成一个Url对象,从而获取想要的信息。
var url = require('url'); console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));
path模块能够用来处理本地文件目录。
var path = require('path'); // 解析当前目录 var workDir = path.resolve('.'); // 组合完整的文件路径 var filePath = path.join(workDir, 'pub', 'index.html');
crypto模块提供通用的加密和哈希算法。
MD5哈希算法用来给任意数据一个签名,一般用一个十六进制字符串表示:
const crypto = require('crypto'); const hash = crypto.createHash('md5'); hash.update('Hello, world!'); console.log(hash.digest('hex'));
Hmac哈希算法能够利用MD5等算法,另外还须要一个密钥:
const crypto = require('crypto'); const hmac = crypto.createHmac('sha256', 'secret-key'); hmac.update('Hello, world!'); console.log(hmac.digest('hex'));
AES是一种经常使用的对称加密算法,加密与解密使用同一个密钥。crypto模块提供了AES支持,但须要自行封装。DiffieHellman算法是一种密钥交换协议,可让双方自行协商一个密钥。crypto模块还能够处理数字证书。
使用Node.js开发Web服务器端,有几点好处:
针对Node.js,出现了不少后端相关的Web框架、ORM框架、模板引擎、测试框架、构建工具等。
Express是第一代最流行的Web服务端框架,它对Node.js的http进行了封装。虽然Express的API很是简单,可是因为是基于ES5,要实现异步,只能使用回调。若是异步嵌套层次过多,代码很难理解。
var express = require('express'); var app = express(); app.get('/', function (req, res) { res.send('Hello World!'); }); app.listen(3000, function () { console.log('Example app listening on port 3000!'); });
koa1基于ES6,使用generator实现异步。虽然使用generator在写法上比回调简单,但其本意并非用于异步。真正设计用来实现异步的是Promise,但Promise的写法过于复杂。
var koa = require('koa'); var app = koa(); app.use('/test', function *() { yield doReadFile1(); var data = yield doReadFile2(); this.body = data; }); app.listen(3000);
koa2基于ES7,使用Promise和关键字async
配合实现异步,同时兼容generator的写法。
app.use(async (ctx, next) => { await next(); var data = await doReadFile(); ctx.response.type = 'text/plain'; ctx.response.body = data; });
ORM技术是将关系型数据库的表结构映射到对象上,Sequelize返回Promise对象,能够更好地进行异步处理。
ES6:
Pet.findAll() .then(function (pets) { for (let pet in pets) { console.log(`${pet.id}: ${pet.name}`); } }).catch(function (err) { // error });
ES7:
(async () => { var pets = await Pet.findAll(); })();
要想使用Sequelize操做数据库,首先须要建立一个Sequelize实例。而后定义数据模型Model,使用Sequelize映射数据库表。这样就能够调用实例的相应方法来对数据库进行操做。
Sequelize操做数据库的通常步骤:
Node.js默认使用Jade做为模板引擎(现更名为Pug)。Jade是Node.js的一个模块,jade文件能够被预编译为.js文件,也能够被编译为目标html代码。
Mocha是JavaScript的单元测试框架,既能够在浏览器环境运行,也能够在Node.js的环境运行。
特色:
WebSocket利用HTTP协议创建链接,在浏览器和服务器之间创建双向通讯的通道,服务器能够主动向浏览器发送消息,而不须要经过浏览器发送请求。
首先,WebSocket链接必须由浏览器发起,由于请求协议是一个标准的HTTP请求。
GET ws://localhost:3000/ws/chat HTTP/1.1 Host: localhost Upgrade: websocket Connection: Upgrade Origin: http://localhost:3000 Sec-WebSocket-Key: client-random-string Sec-WebSocket-Version: 13
与普通HTTP请求的区别:
ws://
开头Upgrade: websocket
和Connection: Upgrade
表示链接将被转换为WebSocket链接Sec-WebSocket-Key
用于标识这个链接Sec-WebSocket-Version
指定WebSocket的协议版本而后,若是服务器接受请求,会返回响应:
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: server-random-string
其中,响应码101表示将切换协议,切换后的协议经过Upgrade来指定。
在Node.js中,最经常使用的WebSocket模块是ws。建立一个WebSocket的服务器实例:
const WebSocket = require('ws'); const WebSocketServer = WebSocket.Server; const wss = new WebSocketServer({ port: 3000 });
若是有WebSocket请求接入,wss对象能够响应connection事件来处理这个WebSocket。对于每一个WebSocket链接,都要对它绑定某些事件方法来处理不一样的事件。
参考文章:
廖雪峰:Node.js教程