nodeJS笔记——参考菜鸟教程
菜鸟教程地址:https://www.runoob.com/nodejs/nodejs-tutorial.html
一、node.js下载安装。
源码下载地址:https://nodejs.org/en/download/
安装包下载地址:https://nodejs.org/dist/
node --version 查看使用版本
无脑操作安装node.js
创建第一个node.js应用:
1.server.js
var http = require(‘http’);
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8888);
// 终端打印如下信息
console.log(‘Server running at http://127.0.0.1:8888/’);
终端上执行以下代码:
node 1.server.js
二、NPM使用介绍
主要用途:
允许用户从NPM服务器下载别人编写的第三方包到本地使用。
允许用户从NPM服务器下载并安装别人编写的命令行程序到本地使用。
允许用户将自己编写的包或命令行程序上传到NPM服务器供别人使用。
查看版本:
npm --version
版本升级:
npm install npm -g
使用npm命令安装模块
使用npm命令安装常用的Node.js web框架模块express:
npm install express
(安装好之后,express包就放在了工程目录下的node_modules目录中,因此在代码中只需要通过require(‘express’)的方式就好,无需指定第三方包路径。
使用package.json:位于模块的目录下,用于定义包的属性。
属性说明:
name-包名。
version-包的版本
description-包的描述
homepage-包的官网URL
author-包的作者姓名
contributors-包的其他贡献者姓名
dependencies-依赖包列表。
repository-包代码存放的地方的类型,可以是git或是svn,git可在Github上。、
main-main字段指定了程序的主入口文件,require(‘moduleName’)就会加载这个文件,这个字段的默认值是模块根目录下面的index.js
keywords–关键字
卸载模块:npm uninstall express
使用npm ls命令查看包是否还在
更新模块:npm update express
搜索模块:npm search express
创建模块:npm init
npm资源库中注册用户:(使用邮箱注册)npm adduser
发布模块: npm publish
三、Node.js REPL(交互式解释器)
Node 自带了交互式解释器,可以执行以下任务:
读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。
执行 - 执行输入的数据结构
打印 - 输出结果
循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
输入以下命令来启动Node的终端:node
输入简单的表达式来计算结果:
1+4
使用变量:使用var关键字的变量可以使用console.log()来输出变量。]
多行表达式:执行一个for循环:
var x=0;
do{
x++;
console.log(“x:”+x);
}while(x<5);
下划线()变量:使用下划线()获取上一个表达式的运算结果:
var x=20
var y=20
x+y
var sum=_
console.log(sum)
REPL 命令
ctrl + c - 退出当前终端。
ctrl + c 按下两次 - 退出 Node REPL。
ctrl + d - 退出 Node REPL.
向上/向下 键 - 查看输入的历史命令
tab 键 - 列出当前命令
.help - 列出使用命令
.break - 退出多行表达式
.clear - 退出多行表达式
.save filename - 保存当前的 Node REPL 会话到指定文件
.load filename - 载入当前 Node REPL 会话的文件内容。
四、回调函数
1.阻塞代码实例:
创建一个文件input.txt
内容:nodejs is best
创建main.js文件,代码如下:
var fs = require(“fs”);
var data=fs.readFileSync(‘input.txt’);
console.log(data.toString());
console.log(“程序执行结束”);
执行代码结果:
node main.js
nodejs is best
程序执行结束!
2.非阻塞代码实例:
创建一个文件input.txt
内容:nodejs is best
创建2.main.js文件,代码如下:
var fs= require(“fs”);
fs.readFile(‘input.txt’,function(err,data){
if(err) return console.log.error(err);
console.log(data.toString());
});
console.log(“程序执行结束!”);
执行结果:
node 2.main.js
程序执行结束!
nodejs is best
第一个实例在文件读取完后才执行程序。 第二个实例我们不需要等待文件读取完,这样就可以在读取文件时同时执行接下来的代码,大大提高了程序的性能。阻塞是按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数,我们就需要写在回调函数内。
五、事件循环
通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件
实例:
// 引入 events 模块
var events = require(‘events’);
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected() {
console.log(‘连接成功。’);
// 触发 data_received 事件
eventEmitter.emit(‘data_received’);
}
// 绑定 connection 事件处理程序
eventEmitter.on(‘connection’, connectHandler);
// 使用匿名函数绑定 data_received 事件
eventEmitter.on(‘data_received’, function(){
console.log(‘数据接收成功。’);
});
// 触发 connection 事件
eventEmitter.emit(‘connection’);
console.log(“程序执行完毕。”);
执行结果:
node 5.event.js
连接成功。
数据接收成功。
程序执行完毕。
六、EventEmitter类
实例:
//6.event.js 文件
var EventEmitter = require(‘events’).EventEmitter;
var event = new EventEmitter();
event.on(‘some_event’, function() {
console.log(‘some_event 事件触发’);
});
setTimeout(function() {
event.emit(‘some_event’);
}, 1000);
执行:
node 6.event.js
some_event 事件触发
解释:运行这段代码,1 秒后控制台输出了 ‘some_event 事件触发’。其原理是 event 对象注册了事件 some_event 的一个监听器,然后我们通过 setTimeout 在 1000 毫秒以后向 event 对象发送事件 some_event,此时会调用some_event 的监听器。
EventEmitter 的每个事件由一个事件名和若干个参数组成,事件名是一个字符串,通常表达一定的语义。对于每个事件,EventEmitter 支持 若干个事件监听器。
当事件触发时,注册到这个事件的事件监听器被依次调用,事件参数作为回调函数参数传递。
实例:
//7.event.js
var events=require(‘events’);
var emitter =new events.EventEmitter();
emitter.on(‘someEvent’,function(arg1, arg2) { //绑定事件函数
console.log(‘listener1’, arg1, arg2);
});
emitter.on(‘someEvent’, function(arg1, arg2) { //绑定事件函数
console.log(‘listener2’, arg1, arg2);
});
emitter.emit(‘someEvent’, ‘arg1 参数’, ‘arg2 参数’); //触发一个事件
执行代码:
node 7.event.js
执行结果:
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数
实例:
//8.event.js
var events = require(‘events’);
var eventEmitter = new events.EventEmitter();
// 监听器 #1
var listener1 = function listener1() {
console.log(‘监听器 listener1 执行。’);
}
// 监听器 #2
var listener2 = function listener2() {
console.log(‘监听器 listener2 执行。’);
}
// 绑定 connection 事件,处理函数为 listener1
eventEmitter.addListener(‘connection’, listener1);
// 绑定 connection 事件,处理函数为 listener2
eventEmitter.on(‘connection’, listener2);
var eventListeners = eventEmitter.listenerCount(‘connection’);
console.log(eventListeners + " 个监听器监听连接事件。");
// 处理 connection 事件
eventEmitter.emit(‘connection’);
// 移除监绑定的 listener1 函数
eventEmitter.removeListener(‘connection’, listener1);
console.log(“listener1 不再受监听。”);
// 触发连接事件
eventEmitter.emit(‘connection’);
eventListeners = eventEmitter.listenerCount(‘connection’);
console.log(eventListeners + " 个监听器监听连接事件。");
console.log(“程序执行完毕。”);
执行程序:node 8.event.js
执行结果:
2 个监听器监听连接事件。
监听器 listener1 执行。
监听器 listener2 执行。
listener1 不再受监听。
监听器 listener2 执行。
1 个监听器监听连接事件。
程序执行完毕。
error事件
实例:9.error.js
var events=require(‘events’);
var emitter = new events.EventEmitter();
emitter.emit(‘error’);
七、Buffer(缓冲区)
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。
但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
* Buffer与字符编码:Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换。
eg://10.buffer.js
const buf = Buffer.from(‘runoob’, ‘ascii’);
// 输出 72756e6f6f62
console.log(buf.toString(‘hex’));
// 输出 cnVub29i
console.log(buf.toString(‘base64’));
*创建Buffer类
Buffer.alloc(size[, fill[, encoding]]): 返回一个指定大小的 Buffer 实例,如果没有设置 fill,则默认填满 0
Buffer.allocUnsafe(size): 返回一个指定大小的 Buffer 实例,但是它不会被初始化,所以它可能包含敏感的数据
Buffer.allocUnsafeSlow(size)
Buffer.from(array): 返回一个被 array 的值初始化的新的 Buffer 实例(传入的 array 的元素只能是数字,不然就会自动被 0 覆盖)
Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。
Buffer.from(buffer): 复制传入的 Buffer 实例的数据,并返回一个新的 Buffer 实例
Buffer.from(string[, encoding]): 返回一个被 string 的值初始化的新的 Buffer 实例
eg://11.buffer.js
// 创建一个长度为 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);
// 创建一个长度为 10、且用 0x1 填充的 Buffer。
const buf2 = Buffer.alloc(10, 1);
// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据,
// 因此需要使用 fill() 或 write() 个重写。
const buf3 = Buffer.allocUnsafe(10);
// 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);
// 创建一个包含 UTF-8 字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');
// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');
*写入缓冲区
格式:buf.write(string[, offset[, length]][, encoding])
string - 写入缓冲区的字符串。
offset - 缓冲区开始写入的索引值,默认为 0 。
length - 写入的字节数,默认为 buffer.length
encoding - 使用的编码。默认为 'utf8' 。
eg://12.buffer.js
buf = Buffer.alloc(256);
len = buf.write("www.runoob.com");
console.log("写入字节数 : "+ len);
执行: node 12.buffer.js
执行结果:写入字节数 : 14
* 从缓冲区读取数据
格式:buf.toString([encoding[, start[, end]]])
encoding - 使用的编码。默认为 ‘utf8’ 。
start - 指定开始读取的索引位置,默认为 0。
end - 结束位置,默认为缓冲区的末尾
eg://13.bufferR.js
buf = Buffer.alloc(26);
for (var i = 0 ; i < 26 ; i++) {
buf[i] = i + 97;
}
console.log( buf.toString(‘ascii’)); // 输出: abcdefghijklmnopqrstuvwxyz
console.log( buf.toString(‘ascii’,0,5)); //使用 ‘ascii’ 编码, 并输出: abcde
console.log( buf.toString(‘utf8’,0,5)); // 使用 ‘utf8’ 编码, 并输出: abcde
console.log( buf.toString(undefined,0,5)); // 使用默认的 ‘utf8’ 编码, 并输出: abcde
执行: node 13.bufferR.js
执行结果:
abcdefghijklmnopqrstuvwxyz
abcde
abcde
abcde
*将Buffer转换为JSON对象
语法:buf.toJSON()
eg://14.bufferJson.js
const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);
// 输出: {"type":"Buffer","data":[1,2,3,4,5]}
console.log(json);
const copy = JSON.parse(json, (key, value) => {
return value && value.type === 'Buffer' ?
Buffer.from(value.data) :
value;
});
// 输出: <Buffer 01 02 03 04 05>
console.log(copy);
执行:node 14.bufferJson.js
执行结果:
{“type”:“Buffer”,“data”:[1,2,3,4,5]}
<Buffer 01 02 03 04 05>
八、js Stream (流)
* 从流中读取数据
eg://input.txt文件。内容如下
//15.main.js 文件
var fs = require(“fs”);
var data = ‘’;
// 创建可读流
var readerStream = fs.createReadStream(‘input.txt’);
// 设置编码为 utf8。
readerStream.setEncoding(‘UTF8’);
// 处理流事件 --> data, end, and error
readerStream.on(‘data’, function(chunk) {
data += chunk;
});
readerStream.on(‘end’,function(){
console.log(data);
});
readerStream.on(‘error’, function(err){
console.log(err.stack);
});
console.log(“程序执行完毕”);
执行:node 15.main.js
执行结果:
程序执行完毕
nodejs is best
* 写入流
eg://16.main.js
var fs = require("fs");
var data = 'zhangge is beautiful';
// 创建一个可以写入的流,写入到文件 output.txt 中
var writerStream = fs.createWriteStream('output.txt');
// 使用 utf8 编码写入数据
writerStream.write(data,'UTF8');
// 标记文件末尾
writerStream.end();
// 处理流事件 --> finish、error
writerStream.on('finish', function() {
console.log("写入完成。");
});
writerStream.on('error', function(err){
console.log(err.stack);
});
console.log("程序执行完毕");
执行:node 16.main.js
执行结果: 程序执行完毕
写入完成
*管道流
实例:读取一个文件的内容,写入到另外一个文件中
//17.main.js
var fs=require(“fs”);
//创建一个可读流
var readerStream=fs.createReadStream(‘input.txt’);
//创建一个可写流
var writeStream=fs.createWriteStream(‘output.txt’);
//管道读写操作
//读取input.txt文件内容,并将内容写到output.txt文件中
readerStream.pipe(writerStream);
console.log(“程序执行完毕”);
执行:node 17.main.js
执行结果:
nodejs is best
*链式流:链式是通过连接输出流到另外一个流并创建多个流操作链的机制。链式流一般用于管道操作。接下来我们就是用管道和链式来压缩和解压文件。
实例://18.compress.js
var fs=require("fs");
var zlib=require('zlib');
//压缩input.txt文件为input.txt.gz
fs.createReadStream('input.txt')
.pipe(zlib.createGzip())
.pipe(fs.createWriteStream('input.txt.gz'));
console.log(“文件压缩完成.”);
执行:node compress.js
执行结果:文件压缩完成
九.模块系统
十、函数
十一、路由
实例:19.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;
//20.router.js
function route(pathname) {
console.log("About to route a request for " + pathname);
}
exports.route = route;
//21.index.js
var server = require("./19.server");
var router = require("./20.router");
server.start(router.route);
十二、全局对象
十三、常用工具
十四、文件系统
十五、GET/Post请求
* 获取GET请求:由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此你可以手动解析后面的内容作为GET请求的参数。node.js 中 url 模块中的 parse 函数提供了这个功能。
实例://22.get.js
var http=require(‘http’);
var url=require(‘url’);
var util=require(‘util’);
http.createServer(function(req,res){
res.writeHead(200,{‘Content-Type’:‘text/plain;charset=utf-8’});
res.end(util.inspect(url.parse(req.url,true)));
}).listen(3000);
console.log(“Server Start”);
获取URL的参考://23.get.js
var http=require(‘http’);
var url=require(‘url’);
var util=require(‘util’);
http.createServer(function(req,res){
res.writeHead(200,{‘Content-Type’:‘text/plain’});
//解析URL参数
var params =url.parse(req.url,true).query;
res.write(“网站名:”+params.name);
res.write("\n");
res.write(“网站URL:”+params.url);
res.end();
}).listen(3000);
console.log(“Sever Start”);
* POST请求:POST 请求的内容全部的都在请求体中,http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。比如上传文件,而很多时候我们可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所以 node.js 默认是不会解析请求体的,当你需要的时候,需要手动来做。
实例:24.post.js(表单通过POST提交并输出数据)
var http=require(‘http’);
var querystring=require(‘querystring’);
var postHTML=
‘
‘’ +
‘’ +
'网站名:
’ +
'网站 URL:
’ +
‘’ +
‘’ +
‘’;
http.createServer(function(req,res){
var body="";
req.on(‘data’,function(chunk){
body+=chunk;
});
req.on(‘end’,function(){
//解析参数
body=querystring.parse(body);
//设置响应头部信息及编码
res.writeHead(200,{‘Content-Type’:‘text/html;charset=utf-8’});
if(body.name && body.url){
res.write(“网站名:”+body.name);
res.write("
");
res.write("网站名URL:“+body.url);
}else{//输出表单
res.write(postHTML);
}
res.end();
});
}).listen(3000);
console.log(“Server Start”);
十六、工具模块
十七、Web模块
实例:一个最基本的 HTTP 服务器架构(使用 8080 端口)//25.http.js
var http = require(‘http’);
var fs = require(‘fs’);
var url = require(‘url’);
// 创建服务器
http.createServer( function (request, response) {
// 解析请求,包括文件名
var pathname = url.parse(request.url).pathname;
// 输出请求的文件名
console.log(“Request for " + pathname + " received.”);
// 从文件系统中读取请求的文件内容
fs.readFile(pathname.substr(1), function (err, data) {
if (err) {
console.log(err);
// HTTP 状态码: 404 : NOT FOUND
// Content Type: text/html
response.writeHead(404, {‘Content-Type’: ‘text/html’});
}else{
// HTTP 状态码: 200 : OK
// Content Type: text/html
response.writeHead(200, {‘Content-Type’: ‘text/html’});
// 响应文件内容
response.write(data.toString());
}
// 发送响应数据
response.end();
});
}).listen(8080);
// 控制台会输出以下信息
console.log(‘Server running at http://127.0.0.1:8080/’);
//26.index.html
我的第一个标题
我的第一个段落。
* 创建客户端:Node 创建 Web 客户端需要引入 http 模块, 实例://26.click.js var http=require('http'); //用于请求的选项 var options={ host:'localhost', port:'8080', path:'/26.index.html' }; //处理响应回调函数 var callback=function(response){ //不断更新数据 var body=''; response.on('data',function(data){ body+=data; }); response.on('end',function(){ //数据接受完成 console.log(body); }); } //向服务端发送请求 var req=http.request(options,callback); req.end(); #### 十八、Express框架:Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。使用 Express 可以快速地搭建一个完整功能的网站。
Express 框架核心特性:
.可以设置中间件来响应 HTTP 请求。
.定义了路由表用于执行不同的 HTTP 请求动作。
.可以通过向模板传递参数来动态渲染 HTML 页面。
- 安装Express
npm install express --save - 安装完之后查看express使用的版本号:npm list express
- 第一个Express框架实例
//27.express_demo.js
var express =require(‘express’);
var app=express();
app.get(’/’,function(req,res){
res.send(‘Hello World’);
})
var server=app.listen(8081,function(){
var host=server.address().address
var port=server.address().port
console.log(“应用实例,访问地址为 http://%s:%s”,host,port)
})
执行:node 27.express_demo.js
执行结果:
应用实例,访问地址为 http://127.0.0.1:8081
十九、RESTful API
二十、多进程
二十一、JXcore打包
二十二、MySQL
- 安装数据库
npm install mysql - 连接数据库
实例:44.test.js
var mysql = require(‘mysql’);
var connection = mysql.createConnection({
host : ‘localhost’,
user : ‘root’,
password : ‘root’,
port: ‘3306’,
database: ‘test’
});
connection.connect();
var sql = ‘SELECT * FROM websites’;
//查
connection.query(sql,function (err, result) {
if(err){
console.log(’[SELECT ERROR] - ',err.message);
return;
}
console.log('--------------------------SELECT----------------------------');
console.log(result);
console.log('------------------------------------------------------------\n\n');
});
connection.end();