Node 基础
nodejs api
Nodejs 中的模块化
Node 应用由模块组成,采用 CommonJS
模块规范。
CommonJS
就是模块化的标准,nodejs
就是 CommonJS
(模块化)的实现
在 Node中,模块分为两类:
一类是 Node 提供的模块,称为核心模块;另一类是用户编写的模块,称为文件模块。
- 核心模块部分在 Node 源代码的编译过程中,编译进了二进制执行文件。在 Node 进 程启动时,部分核心模块就被直接加载进内存中,所以这部分核心模块引入时,文件定位和 编译执行这两个步骤可以省略掉,并且在路径分析中优先判断,所以它的加载速度是最快的。 如:HTTP 模块 、URL 模块、Fs模块都是 nodejs 内置的核心模块,可以直接引入使用。
- 文件模块则是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、 速度相比核心模块稍微慢一些,但是用的非常多。这些模块需要我们自己定义。接下来我 们看一下 nodejs 中的自定义模块。
http 模块
1、引入 http 模块
var http = require("http");
2、创建服务器
接下来我们使用 http.createServer()
方法创建服务器,并使用 listen
方法绑定 8888 端口。函数通过 request
, response
参数来接收和响应数据。
var http = require('http');
http.createServer(function (request, response) {
//request 参数表示请求,response 表示响应
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 设置 HTTP 头部,状态码是 200,文件类型是 html,字符集是 utf8
console.log("服务器接收到了请求" + req.url);
response.writeHead(200,{"Content-Type":"text/html;charset=UTF-8"});
// 发送响应数据 "Hello World"
res.end("哈哈哈哈,我买了一个 iPhone" + (1+2+3) + "s"); // End 方法使 Web 服务器停止处理脚本并返回当前结果
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
3.运行程序
用命令行切换到程序对应目录。通过 node 命令运行程序。
node server.js
浏览器运行
URL 模块
url.parse() //解析 URL
url.format(urlObject) //是上面 url.parse() 操作的逆向操作
url.resolve(from, to) //添加或者替换地址
2
3
1.url.parse()
D:\Users\18060064\Desktop\Git\FE.github.io>node
> url.parse('http://www.baidu.com?name=zhangsan&age=23')
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.baidu.com',
port: null,
hostname: 'www.baidu.com',
hash: null,
search: '?name=zhangsan&age=23',
query: 'name=zhangsan&age=23',
pathname: '/',
path: '/?name=zhangsan&age=23',
href: 'http://www.baidu.com/?name=zhangsan&age=23' }
>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> url.parse('http://www.baidu.com?name=zhangsan&age=23', true)
Url {
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.baidu.com',
port: null,
hostname: 'www.baidu.com',
hash: null,
search: '?name=zhangsan&age=23',
query: [Object: null prototype] { name: 'zhangsan', age: '23' },
pathname: '/',
path: '/?name=zhangsan&age=23',
href: 'http://www.baidu.com/?name=zhangsan&age=23' }
2
3
4
5
6
7
8
9
10
11
12
13
14
2、url.format()
url.format({
protocol: 'http:',
slashes: true,
auth: null,
host: 'www.baidu.com',
port: null,
hostname: 'www.baidu.com',
hash: null,
search: '?name=zhangsan&age=23',
query: [Object: null prototype] { name: 'zhangsan', age: '23' },
pathname: '/',
path: '/?name=zhangsan&age=23',
href: 'http://www.baidu.com/?name=zhangsan&age=23'
})
http://www.baidu.com/?name=zhangsan&age=23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2、url.format()
> url.format('http://www.baidu.com/','/one')
http://www.baidu.com/one
2
QueryString 模块
querysting.escape(str) // 将字符转成浏览器认的
querysting.unescape(str) // 跟escape相反
querysting.parse(str, sep, eq, options) // 将字符串转换成对象 sep分隔键值对的子字符串 默认值: '&' eq 分隔键和值的子字符串 默认值: '='
querysting.stringify(obj, sep, eq, options) // 将对象转换成字符串 sep分隔键值对的子字符串 默认值: '&' eq 分隔键和值的子字符串 默认值: '='
2
3
4
Fs 模块
1. fs.stat 检测是文件还是目录
2. fs.mkdir 创建目录
3. fs.writeFile 创建写入文件
4. fs.appendFile 追加文件
5.fs.readFile 读取文件
6.fs.readdir 读取目录
7.fs.rename 重命名
8. fs.rmdir 删除目录
9. fs.unlink 删除文件
10. fs.createReadStream 从文件流中读取数据
11. fs.createWriteStream 写入文件
12. 管道流
2
3
4
5
6
7
8
9
10
11
12
1. fs.stat 检测是文件还是目录
fs .stat('hello.js', (error, stats) =>{
if(error){
console .log(error)
} else {
console .log(stats)
console .log(`文件:${stats.isFile()}`)
console .log(`目录:${stats.isDirectory()}`)
} })
2
3
4
5
6
7
8
2. fs.mkdir 创建目录
const fs = require ('fs')
fs .mkdir('logs', (error) => {
if(error){
console .log(error)
} else {
console .log('成功创建目录:logs')
}
})
2
3
4
5
6
7
8
9
3. fs.writeFile 创建写入文件
fs .writeFile('logs/hello.log', '您好 ~ \n', (error) => {
if(error) {
console .log(error)
} else {
console .log('成功写入文件')
}
})
2
3
4
5
6
7
4. fs.appendFile 追加文件
fs.appendFile('logs/hello.log', 'hello ~ \n', (error) => {
if(error) {
console .log(error)
} else {
console .log('成功写入文件')
} })
2
3
4
5
6
5.fs.readFile 读取文件
const fs = require ('fs')
fs.readFile('logs/hello.log', 'utf8', (error, data) =>{
if (error) {
console .log(error)
} else {
console .log(data)
}
})
2
3
4
5
6
7
8
9
6.fs.readdir 读取目录
const fs = require ('fs')
fs .readdir('logs', (error, files) => {
if (error) {
console .log(error)
} else {
console .log(files)
}
})
2
3
4
5
6
7
8
9
7.fs.rename 重命名
const fs = require ('fs')
fs .rename('js/hello.log', 'js/greeting.log', (error) =>{
if (error) {
console .log(error)
} else {
console .log('重命名成功')
}
})
2
3
4
5
6
7
8
9
8. fs.rmdir 删除目录
fs.rmdir('logs', (error) =>{
if (error) {
console .log(error)
} else {
console .log('成功的删除了目录:logs')
}
})
2
3
4
5
6
7
9. fs.unlink 删除文件
fs .unlink(`logs/${file}`, (error) => {
if (error) {
console .log(error)
} else {
console .log(`成功的删除了文件: ${file}`)
}
})
2
3
4
5
6
7
10. fs.createReadStream 从文件流中读取数据
const fs = require ('fs')
var fileReadStream = fs .createReadStream('data.json')
let count =0;
var str ='';
fileReadStream .on('data', (chunk) => {
console .log(`${ ++ count } 接收到:${chunk.length}`);
str +=chunk
})
fileReadStream .on('end', () => {
console .log('--- 结束 ---');
console .log( count );
console .log( str );
})
fileReadStream .on('error', (error) => {
console .log(error)
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
11. fs.createWriteStream 写入文件
var fs = require ("fs");
var data = '我是从数据库获取的数据,我要保存起来';
// 创建一个可以写入的流,写入到文件 output.txt 中
var writerStr eam = fs .createWriteStream('output.txt');
// 使用 utf8 编码写入数据
writerStream .write( data ,'UTF8');
// 标记文件末尾
writerStream .end();
// 处理流事件 -- > finish 事件
writerStream .on('finish', function() { /*finish - 所有数据已被写入到底层系统时触发。 */
console .log("写入完成。");
});
writerStre am .on('error', function(err){
console .log(err.stack);
});
console .log("程序执行完毕");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
管道流
管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传 递到另外一个流中
我们把文件比作装水的桶,而水就是文件里的内容,我们用一根管子(pipe)连接两个桶使得水从一个桶流入另一个桶,这样就慢慢的实现了大文件的复制过程。
以下实例我们通过读取一个文件内容并将内容写入到另外一个文件中。
var fs = require ("fs");
// 创建一个可读流
var readerStream = fs .createReadStream('input.txt');
// 创建一个可写流
var writerStream = fs .createWriteStream('output.txt');
// 管道读写操作
// 读取 input.txt 文件内容,并将内容写入到 output.txt 文件中 readerStream .pipe( writerStream );
console .log("程序执行完毕");
2
3
4
5
6
7
8
Nodejs 的单线程 非阻塞 I/O 事件驱动
在 Java、PHP 或者.net 等服务器端语言中,会为每一个客户端连接创建一个新的线程。 而每个线程需要耗费大约 2MB 内存。也就是说,理论上,一个 8GB 内存的服务器可以同时 连接的最大用户数为 4000 个左右。要让 Web 应用程序支持更多的用户,就需要增加服务器 的数量,而 Web 应用程序的硬件成本当然就上升了。
Node.js 不为每个客户连接创建一个新的线程,而仅仅使用一个线程。当有用户连接了, 就触发一个内部事件,通过非阻塞 I/O、事件驱动机制,让 Node.js 程序宏观上也是并行的。
使用 Node.js,一个 8GB 内存的服务器,可以同时处理超过4 万用户的连接。
events 模块
Node.js 有多个内置的事件,我们可以通过引入 events
模块,并通过实例化 EventEmitter
类来绑定和监听事件。
// 引入 events 模块
var events = require('events');
var EventEmitter=new events.EventEmitter(); /*实例化事件对象*/
EventEmitter.on('toparent',function(){
console.log('接收到了广播事件');
})
setTimeout(function(){
console.log('广播');
EventEmitter.emit('toparent'); /*发送广播*/
},1000)
2
3
4
5
6
7
8
9
10
Get、Post
超文本传输协议(HTTP)的设计目的是保证客户端机器与服务器之间的通信。
在客户端和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST。
GET - 从指定的资源请求数据。(一般用于获取数据)
POST - 向指定的资源提交要被处理的数据。(一般用于提交数据)
获取 GET 传值:
var urlinfo= url .parse(req.url,true);
urlinfo.query();
2
获取 POST 传值:
var postData = ''; // 数据块接收中
req.on('data', function (postDataChunk) {
postData += postDataChunk;
}); // 数据接收完毕,执行回调函数
req.on('end', function () {
try {
postData = JSON.parse(postData);
} catch (e) { }
req.query = postData;
console .log( querystring .parse(postData));
});
2
3
4
5
6
7
8
9
10
11
路由
官方解释:
路由(Routing)是由一个 URI(或者叫路径)和一个特定的 HTTP 方法(GET、POST 等)组成 的,涉及到应用如何响应客户端对某个网站节点的访问。
非官方解释:
路由指的就是针对不同请求的 URL,处理不同的业务逻辑。