Node.js笔记(1)
根据B站黑马记录的笔记,并且也做了对应的思维导图,搭配食用更佳
Node.JS简介
何为Node.JS
- Node.JS为JavaScript运行时
- Node.JS是JavaScript的运行平台
- 它既不是一门语言,也不是框架,它是一个平台
Node.JS中的JS
- Node.JS没有dom和bom
- EcmaScript
- Node.JS在JavaScript执行环境中为JavaScript提供一些服务器级别的API
- 文件读写
- 网络服务构建
- 网络通信
- http服务器
- ……
Node.JS构建于Chrome的V8引擎
- 代码只是具有特定格式的字符串
- 引擎可以认识它,帮你解析和执行
- Google Chrome的V8引擎是目前公认的解析执行JavaScript代码最快的
- Node.js的作者把Google Chrome中的V8引擎移植出来,开发了一个独立的JavaScript运行时环境
Node.JS的特性
- envent-driven 事件驱动
- non-blocking I/O mode 非阻塞I/O模型(异步)
- ightweight and efficent. 轻量和高效
Node.JS的作用
web服务器后台
命令行工具
*npm(node)- git(c语言)
- hexo(node)
- …
其它
npm为世界上最大的开源生态系统
初识
安装配置
- 下载:https://nodejs.org/en/
- 安装node环境
- 检测node环境
*开启命令行提示符(cmd)
*输入node --vesion
*或node -v
*正常状态下返回版本号 - 解析执行JavaScript
*创建和编写JavaScript脚本文件
*打开终端(cmd),定位脚本文件所在位置(也就是执行脚本所在文件目录)
*输入node 文件名进行执行
注意:文件名不要使用Node.JS命名,并且最好不用中文
fs
文件操作模块
- 浏览器中的 JavaScript 没有文件操作能力
- Node中的 JavaScript 具有文件操作能力
- fs 是 file-system 的简写,为文件系统的意思
- 在 Node 中如果想要进行文件操作,就必须引入 fs 这个核心模块
- 在 fs 这个核心模块中,就提供了所有文件操作相关的 API,
- fs.readFile 用来读取文件
- fs.writeFile用来写入文件
- 文件中存储的都是二进制数据,用toString()方法转换为字符串
读取文件
1.使用require
方法加载fs
核心模块
2.使用readFile
函数读取文件
两个参数,第一个为文件路径,第二个为回调函数
回调函数中有两个参数
第一个参数为返回错误,第二个为数据
成功:error: null; data: 返回数据
失败: error: 错误对象; data: undefined
可以利用
error
进行语句判断
1 | //使用node中的fs模块读取文件(使用require语句) |
写入文件
1.使用require方法加载fs核心模块
2.使用writeFile函数读取文件
包含三个参数
第一个参数为文件路径及名称
第二个参数为写入文本内容
第三个参数为回调函数
回调函数中的
error
参数
文件写入成功 :error
是null
文件写入失败:error
就是错误对象1
2
3
4
5
6
7
8
9var a = require('fs');
a.writeFile('你是最棒的.md','你是最棒的',function(error) {
console.log(error);
if (error === null) {
console.log("写入成功");
} else {
console.log("写入失败");
}
});
http
IP地址和端口号
- IP地址用来定位计算机
- 端口号用来定位具体应用程序
- 所有需要联网的应用程序都需要占用一个端口号
- 计算机默认端口号尽量不要访问
- 80
- …
服务器
- 提供服务:为数据服务
- 发请求
- 接收请求
- 处理请求
- 反馈(发送响应)
- 当客户端请求过来,就会自动触发服务器的request请求事件,然后执行第二个参数:回调处理函数
启动服务器
1.加载http模块
2.创建web服务对象
3.监听(注册)request事件
4.绑定端口号,启动服务
1 | //加载http模块 |
request请求事件处理函数
- request 请求事件处理函数,需要接收两个参数:request和response
- request 请求对象:请求对象可以用来获取客户端的一些请求信息,例如请求路径
- reponse响应对象:响应对象可以用来给客户端发送响应消息
- 响应内容只能是二进制数据或者字符串
- 转出数据内容为其他数据类型时需转化格式
- 一个请求对应一个响应,已经结束响应则无法重复发送响应
- 无请求就无响应
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57//加载http模块
var http = require('http')
//创建web服务
var server = http.createServer()
//监听request事件,设置请求处理函数,函数参数调用request和response
server.on('request', function (request,response) {
console.log('请求路径为' + request.url) //request.url为请求路径
console.log('请求我的客户端的地址是:', request.socket.remoteAddress,
request.socket.remotePort)
//响应条件判断,判断请求路径
//json测试
var phone = [
{
name: 'apache',
price: 80000,
lcd: 'a'
},
{
name: 'asdfg',
price: 5000,
lcd: 'd'
},
{
name: 'hello',
price: 25000,
lcd: 'c'
}]
switch (request.url) {
case '/':
response.write('你好啊')
response.end()
break;
case '/a':
response.write('hello')
response.end()
break;
case '/b':
response.end('leihoua') //可以直接使用.end()函数
break;
case '/c':
response.end(JSON.stringify(phone)) //转化为字符串格式
break;
default:
response.write('当前路径未存在')
response.end()
break;
}
})
//绑定端口号,启动服务
server.listen(3000,function() {
console.log('服务器启动成功了,可以通过 http://127.0.0.1:3000/ 来进行访问')
})
Content-type
- 服务器默认发送的数据为utf8编码内容
- 浏览器在不知道浏览器响应内容编码的情况下,会按当前操作系统默认编码解析
- 中文操作系统默认编码为gbk
- 在 http 协议中,Content-Type 就是用来告知对方我给你发送的数据内容是什么类型
- 不同的资源对应的 Content-Type 是不一样
- Content-Type工具:http://tool.oschina.net/commons
1 | //加载http模块 |
返回文件(http-fs)
发送的并不是文件,本质上来讲发送是文件的内容(一堆字符串)
当浏览器收到服务器响应内容之后,就会根据你的 Content-Type 进行对应的解析处理
结合 fs 发送文件中的数据
字符数据需指定编码
图片不需要指定编码
根据url返回内容
加载指定模块
创建服务对象
监听request事件
- 判断请求的url
- 为对应的url返回文件
- 读取文件内容
- 响应输出文件内容(注意转换格式与编码)
绑定端口号,启动服务
1 | //加载指定模块 |
浏览器输入路径打开文件
需求:用户在浏览器输入文件名即可访问该文件内容
- 将用户输入的文件转化为fs所找文件路径
- fs读取文件
- res响应文件内容
- 输出文件内容
1 | //引用模块 |
重定向
状态码301和302
301
永久性的重定向,搜索引擎在抓取新内容的同时将旧网址替换为重定向之后的网址
302
暂时性跳转,搜索引擎抓取新的内容的同时保留旧网址
服务器返回302时,搜索引擎认为新网址时暂时的
path
路径操作模块
基本操作
- path.basename:获取路径的文件名,默认包含扩展名
- path.dirname:获取路径中的目录部分
- path.extname:获取一个路径中的扩展名部分
- path.parse:把路径转换为对象
- root:根路径
- dir:目录
- base:包含后缀名的文件名
- ext:后缀名
- name:不包含后缀名的文件名
- 🔺path.join:拼接路径(第二个参数会自动判断/是否多余)
- path.isAbsolute:判断一个路径是否为绝对路径
body-parser
简介
body post解析中间件
处理程序之前,在中间件中对传入的请求体进行解析(response body)
处理post请求体
body-parser
提供四种解析器
JSON body parser
Raw body parser
Text body parser
URL-encoded form body parser
安装
1 | npm i body-parser |
引入
1 | var bodyParse = require("body-parse") |
配置
1 | // parse application/x-www-form-urlencoded |
使用
1 | router.post('/login',function(req,res){ |
原生获取post请求体方式
记得先引入querystring
模块
querystring
用作分割请求体内容并转化为对象格式
因为有时候会用到文件上传,所以这里要判断数据请求头的content-type
,如果是multipart/form-data
,则让formidable
中间件去处理,否则自己处理
1 | app.use((req, res, next) => { |
node中的其他成员
__dirname() __filename
- __dirname:动态获取当前模块文件所处目录的绝对路径
- __filename: 动态获取当前文件的绝对路径
在文件操作中,使用相对路径是不可靠的,因为node中文件操作的路径被设计为相对于执行node命令所处的路径。为了解决这个问题,需要使用__dirname()
或__filename
把相对路径变为绝对路径(绝对路径不受任何影响)。
在拼接路径的过程中,为了避免手动拼接带来的一些错误,就可以使用path.join()来辅助拼接
1 | var fs = require('fs') |
注意:
模块中的路径标识和文件操作中的相对路径标识不一致
模块中的路径标识就是相对于当前文件模块,不受node命令所处路径影响
node中的模块系统
模块化
何为模块化
- 文件作用域(模块是独立的,在不同的文件使用必须要重新引用)
- 注意: 在node中没有全局作用域,它是文件模块作用域
- 通信规则
- 加载:
require
- 导出:
exports
- 加载:
模块类型
- 核心模块
- 文件操作的fs
- http服务操作的http
- url路径操作模块
- path路径处理模块
- os操作系统信息
- ……
- 第三方模块
- art-template
- 必须通过npm来下载才可以使用
- 自己写的模块
- 自己创建的文件
模块标识
./
相对于当前路径(在文件操作中可省略)
/
在当前模块所处的磁盘根目录
javascript模块化(需补充)
- Node 中的 CommonJS
- 浏览器中的:
- AMD require.js
- CMD sea.js
- es6中增加了官方支持
CommonJS模块规范
- 模块作用域
- 使用require方法来加载模块
- 使用exports接口对象来导出模板中的成员
加载require
使用require
函数加载模块
若调用非核心模块和第三方模块,必须加上相对路径
./
,可以省略后缀名require
作用- 加载文件模块并执行里面的代码
- 拿到被加载文件模块导出的接口对象
1 | var http = require('http') |
require方法加载规则
- 优先从缓存加载(即不会重复调用同个模块中的函数)
- 避免重复加载,提高模块加载效率
- node会自动寻找当前文件路径的node_modules,从而加载第三方包,若没有,则会继续往上一级目录找,直到找到(如没找到则报错)
main.js
1 | require('./a') |
a.js
1 | console.log('a.js 被加载了') |
b.js
1 | console.log('b.js 被加载了') |
所以
1 | exports.a = 2 |
这些值最终会等同于module.exports.a = 2和module.exports.a = 3,同时会被导出
但如果,你这样写代码
1 | exports = 2 |
那么,你相当于改了exports的值,那么它就会与module.exports分道扬镳,它的值也不会等于module导出的值
所以,为了保险起见,新手最好使用module.exports导出你要导出的内容,避免错误