# Node.js学习(基础)
# 基础介绍
# 什么是node.js
- Node.js的本质是一个javascript解析器
- Node.js是javascript的运行环境
- Node.js是一个服务器程序
- Node.js本身使用的是V8引擎
- Node.js不是web服务器
# 为什么要使用node.js
- 为了提供高性能的web服务
- IO性能强大
- 时间处理机制完善
- 天然能够处理DOM
- 社区非常活跃,生态圈日趋完善
# node.js的优势在哪里
- 处理大流量数据
- 适合实时交互的应用
- 完美支持对象数据库
- 异步处理大量并发连接
# 学习node.js的前置知识
- javascript
- ES6
- 一些服务器相关的知识
- 最好在Linux系统下进行开发
# node.js相关的资源和资料
- 官网网站
- 中文社区
- 手册
- 开源代码
# Node.js回调函数
# 什么是回调
- 函数调用方式分为三类:同步调用、回调和异步调用。
- 回调是一种双向调用模式
- 可以通过回调函数来实现回调
# 阻塞与非阻塞
- 阻塞和非阻塞关注的是程序在等待调用结果(消息、返回值)时的状态
- 阻塞就是做不完不准回来
- 非阻塞就是你先做,我先看看有其他事没有,完了告诉我一声
阻塞代码
var fs = require('fs');
var data = fs.readFileSync('data.txt');
console.log(data.toString());
1
2
3
2
3
非阻塞代码
var fs = require('fs');
var data = fs.readFile('data.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log(data.toString());
});
console.log('程序执行完毕');
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# Node.js事件驱动机制
# 事件驱动模型
# 事件处理代码流程
- 引入events 对象,创建eventEmitter对象
- 绑定事件处理程序
- 触发事件
//引入Event模块并创建eventsEmitter对象
var events = require('events');
var eventEmitter = new events.EventEmitter();
//绑定事件处理函数
var connectHandler = function connected() {
console.log('connected被调用!');
}
eventEmitter.on('connection', connectHandler);//完成事件绑定
//触发事件
eventEmitter.emit('connection');
console.log(''程序执行完毕);
//输出结果
//connected被调用!
//程序执行完毕
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Node.js模块化
# 模块化的概念与意义
- 为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统
- 模块是Node.js应用程序的基本组成部分
- 文件和模块是一一对应的。一个Node.js文件就是一个模块
- 这个文件可能是javascript代码、JSON或者编译过的C/C++拓展。
- Node.js中存在4类模块(原生模块和3中文件模块)
# Node.js的模块加载流程
# Node.js的模块加载方式
- 从文件模块缓存中加载
- 从原生模块加载
- 从文件加载
# require方法加载模块
require方法接受一下几种参数的传递:
- http、fs、path等,原生模块
- ./mod或../mod,相对路径的文件模块。
- /pathtomodule/mod,绝对路径的文件模块。
- mod,非原生模块的文件模块
hello.js
//模块的主要逻辑
function Hello() {
var name;
this.setName = function(argName) {
name = argName;
}
this.sayHello = function() {
console.log('Hello' + name);
}
}
//对模块进行导出
module.exports = Hello;
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
main.js
//调用Hello模块
var Hello = require('./hello');
hello = new Hello();
hello.setName('Yideng');
hello.sayHello();
//输出
//Hello Yideng
1
2
3
4
5
6
7
2
3
4
5
6
7
# Node.js函数
# 函数概念
- 在javascript中,一个函数可以作为另一个函数的参数
- 我们可以先定义一个函数,然后传递,也可以再传递参数的地方直接定义函数
- Node.js中函数的使用与javascript类似
# 函数举例
function say (word) {
console.log(word);
}
function execute (someFunction, value) {
someFunction(value);
}
execute(say, "Hello");
1
2
3
4
5
6
7
2
3
4
5
6
7
# 匿名函数
- 我们可以把一个函数作为变量传递
- 不一定“先定义,在传递”,可以直接在另一个函数的括号中定义和传递这个函数。
function excute(someFunction, value) {
someFunction(value);
}
execute(function(word) {console.log(word)}, "Hello");
1
2
3
4
2
3
4
//同样的功能,不同的实现方式
//匿名函数
var http = require("http");
http.creatServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}).listen(8888);
////////////////////
//先定义后传递
var http = require("http");
function onRequest(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Node.js路由
server.js
var http = require("http");
var url = require("url");
function start(route) {
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
route(pathname, response);
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start = start;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
router.js
function route(pathname, response) {
console.log("About to route a request for " + pathname);
if (pathname == '/') {
response.writeHead(200, {
"Content-Type": "text/plain"
});
response.write("Hello World");
response.end();
} else {
response.end(`${pathname}`);
}
}
exports.route = route;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
index.js
var server = require("./server");
var router = require("./router");
server.start(router.route);
1
2
3
4
2
3
4
# Node.js全局对象
# Node.js文件系统
# 打开文件
var fs = require("fs");
// 异步打开文件
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
});
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
执行
$ node file.js
准备打开文件!
文件打开成功!
1
2
3
2
3
# 获取文件信息
var fs = require("fs");
console.log("准备打开文件!");
fs.stat('input.txt', function (err, stats) {
if (err) {
return console.error(err);
}
console.log(stats);
console.log("读取文件信息成功!");
// 检测文件类型
console.log("是否为文件(isFile) ? " + stats.isFile());
console.log("是否为目录(isDirectory) ? " + stats.isDirectory());
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
执行结果
$ node file.js
准备打开文件!
{ dev: 16777220,
mode: 33188,
nlink: 1,
uid: 501,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 40333161,
size: 61,
blocks: 8,
atime: Mon Sep 07 2015 17:43:55 GMT+0800 (CST),
mtime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST),
ctime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST) }
读取文件信息成功!
是否为文件(isFile) ? true
是否为目录(isDirectory) ? false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 读取文件
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开已存在的文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件:");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
console.log(bytes + " 字节被读取");
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
执行结果
$ node file.js
准备打开已存在的文件!
文件打开成功!
准备读取文件:
42 字节被读取
菜鸟教程官网地址:www.runoob.com
1
2
3
4
5
6
2
3
4
5
6
# 写入文件
var fs = require("fs");
console.log("准备写入文件");
fs.writeFile('input.txt', '我是通 过fs.writeFile 写入文件的内容', function(err) {
if (err) {
return console.error(err);
}
console.log("数据写入成功!");
console.log("--------我是分割线-------------")
console.log("读取写入的数据!");
fs.readFile('input.txt', function (err, data) {
if (err) {
return console.error(err);
}
console.log("异步读取文件数据: " + data.toString());
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
执行结果
$ node file.js
准备写入文件
数据写入成功!
--------我是分割线-------------
读取写入的数据!
异步读取文件数据: 我是通 过fs.writeFile 写入文件的内容
1
2
3
4
5
6
2
3
4
5
6
# 关闭文件
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件!");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功");
});
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
执行结果
$ node file.js
准备打开文件!
文件打开成功!
准备读取文件!
菜鸟教程官网地址:www.runoob.com
文件关闭成功
1
2
3
4
5
6
2
3
4
5
6
# 截取文件
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("截取10字节内的文件内容,超出部分将被去除。");
// 截取文件
fs.ftruncate(fd, 10, function(err){
if (err){
console.log(err);
}
console.log("文件截取成功。");
console.log("读取相同的文件");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功!");
});
});
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
执行结果
$ node file.js
准备打开文件!
文件打开成功!
截取10字节内的文件内容,超出部分将被去除。
文件截取成功。
读取相同的文件
site:www.r
文件关闭成功
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 删除文件
var fs = require("fs");
console.log("准备删除文件!");
fs.unlink('input.txt', function(err) {
if (err) {
return console.error(err);
}
console.log("文件删除成功!");
});
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
执行结果
$ node file.js
准备删除文件!
文件删除成功!
1
2
3
2
3
# 创建目录
var fs = require("fs");
// tmp 目录必须存在
console.log("创建目录 /tmp/test/");
fs.mkdir("/tmp/test/",function(err){
if (err) {
return console.error(err);
}
console.log("目录创建成功。");
});
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
执行结果
$ node file.js
创建目录 /tmp/test/
目录创建成功。
1
2
3
2
3
# 读取目录
var fs = require("fs");
console.log("查看 /tmp 目录");
fs.readdir("/tmp/",function(err, files){
if (err) {
return console.error(err);
}
files.forEach( function (file){
console.log( file );
});
});
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
执行结果
$ node file.js
查看 /tmp 目录
input.out
output.out
test
test.txt
1
2
3
4
5
6
2
3
4
5
6
# 删除目录
var fs = require("fs");
// 执行前创建一个空的 /tmp/test 目录
console.log("准备删除目录 /tmp/test");
fs.rmdir("/tmp/test",function(err){
if (err) {
return console.error(err);
}
console.log("读取 /tmp 目录");
fs.readdir("/tmp/",function(err, files){
if (err) {
return console.error(err);
}
files.forEach( function (file){
console.log( file );
});
});
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
执行结果
$ node file.js
准备删除目录 /tmp/test
读取 /tmp 目录
……
1
2
3
4
2
3
4