Node.js是运行在服务端的JavaScript,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好。
其特点:单线程,异步非阻塞I/O,事件驱动,速度快
模块
引用模块使用require
函数
模块加载机制被称为CommonJS
规范。在这个规范下,每个.js
文件都是一个模块,它们内部各自使用的变量名和函数名都互不冲突,例如,hello.js
和main.js
都申明了全局变量var s = 'xxx'
,但互不影响。
exports 向外暴露多个对象
- 对外暴露对象
使用exports.[function name] = [function name]
- 引用暴露的对象
xxx = require('./a')
此时的xxx
等价于a文件中的exports
1 | // func.js |
1 | // index.js |
module.exports 向外暴露单个对象
- 一个模块想要对外暴露变量(函数也是变量),可以用
module.exports = variable;
,输出的变量可以是任意对象、函数、数组等等。 - 一个模块要引用其他模块暴露的变量,用
var ref = require('module_name');
就拿到了引用模块的变量。
1 | // func.js |
1 | // mian.js |
exports
是module.exports
的一个引用,exports
指向的是module.exports
node_modules文件夹
node_modules
是安装node后用来存放用包管理工具下载安装的包的文件夹.
node是如何找到模块的?
阶段1. 粗查阶段
- 如果是node核心模块,就直接返回模块名称
- 如果是引入的第三方npm模块,会返回父级所在文件夹下的
node_modules
,父父级所在文件夹下的node_modules
,依次递归,一直到/node_modules
和用户名下的.node_modules
以及全局环境变量配置的全局安装的模块文件夹组成的数组 - 如果是相对路径引入的模块,会将相对路径和父级路径之间进行一个
path.resolve()
,然后返回
阶段2. 精确查找,获取文件绝对路径
以require('express')
为例
- 先尝试加载
node_modules/express
,这种没有扩展名的文件是否存在 - 尝试按照扩展名规则查找,依次判断
node_modules
文件夹下.js .json .node
结尾的文件名为express
的文件是否存在,返回文件的绝对路径 - 判断
node_modules/express
文件夹下的package.json
是否存在,如果存在,返回main字段指定的文件的绝对路径 - 判断
node_modules/express/index.js
是否存在,存在返回对应文件绝对路径
使用 package.json 管理依赖
一个 package.json 文件可以有以下几点作用:
- 作为一个描述文件,描述了你的项目依赖哪些包
- 允许我们使用 “语义化版本规则” 指明你项目依赖包的版本
- 让你的构建更好地与其他开发者分享,便于重复使用
Http模块
nodejs不需要使用apache、nginx等服务器,nodejs不仅仅实现了一个应用,同时还实现了整个http服务器。
1 | var http = require("http"); |
http模块的createServer
的回调函数中
request
代表客户端的请求数据,是一个可读流request.url
请求的 url 路由request.method
请求的方式(GET、POST…)response
代表服务端的响应数据,是一个可写流response.write(xxx)
往响应中写数据response.end(xxx)
结束写返回数据response.setHeader(xxx)
设置响应头
响应中的内容只能是二进制流或字符串
GET/POST请求
请求方式可以通过request.method
获取
获取GET请求内容
由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?
后面的部分,因此可以手动解析后面的内容作为GET请求的参数。
1 | let request_get = url.parse(request.url, true)['query']; |
获取POST请求内容
POST请求的内容全部的都在请求体中,http.ServerRequest
并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。
比如上传文件,而很多时候我们可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所有node.js
默认是不会解析请求体的, 当你需要的时候,需要手动来做。
1 | var http = require('http'); |
url模块
url.parse()
解析一个url地址,返回一个url对象url.parse(url, bool parseQueryString = false, bool slashesDenoteHost = false)
url
: url地址字符串parseQueryString
: 若为true,返回的url对象中query
属性返回的是一个对象slashesDenoteHost
: 若为true,则//
之后至下一个/
之前的字符串会解析作为host
.
例如,//foo/bar
会解析为{host:'foo',pathname:'/bar'}
而不是{pathname:'//foo/bar'}
.
1 | console.log(url.parse('http://127.0.0.1:5000/test/test?id=1&name=a#123')) |
若第二个参数为true
:
1 | console.log(url.parse('http://127.0.0.1:5000/test/test?id=1&name=a#123', true)) |
url.format()
将一个url对象转化成url字符串
url.format(urlObject)
其中的urlObject
是一个url对象
1 | let urlobj = { |
path模块
path 模块提供了一些用于处理文件路径的小工具
path.parse()
解析并返回路径字符串的对象。
path.parse(pathString)
1 | let file_path = '/var/www/html/index.html' |
path.dirname()
返回路径中代表文件夹的部分
1 | path.dirname('/var/www/html/index.html'); |
path.basename(p[, ext])
返回路径中的最后一部分(文件名)
1 | path.basename('/var/www/html/index.html'); |
path.dirname(p)
返回路径中代表文件夹的部分
1 | path.basename('/var/www/html/index.html'); |
path.extname(p)
返回路径中文件的后缀名,即路径中最后一个.
之后的部分。
如果一个路径中并不包含.
或该路径只包含一个.
且这个.
为路径的第一个字符,则此命令返回空字符串。
1 | path.extname('/var/www/html/index.html'); |
fs模块
Node.js
内置的fs
模块就是文件系统模块,负责读写文件。(file system)
所有与文件操作都是通过fs
核心模块来实现的,包括文件目录的创建、删除、查询以及文件的读取和写入,在 fs
模块中,所有的方法都分为同步和异步两种实现,具有 sync
后缀的方法为同步方法,不具有 sync
后缀的方法为异步方法,在了解文件操作的方法之前有一些关于系统和文件的前置知识,如文件的权限位 mode
、标识位 flag
、文件描述符 fd
等
标识位 flag
NodeJS 中,标识位代表着对文件的操作方式,如可读、可写、即可读又可写等等
符号 | 含义 |
---|---|
r |
读取文件,如果文件不存在则抛出异常。 |
r+ |
读取并写入文件,如果文件不存在则抛出异常。 |
rs |
读取并写入文件,指示操作系统绕开本地文件系统缓存。 |
w |
写入文件,文件不存在会被创建,存在则清空后写入。 |
wx |
写入文件,排它方式打开。 |
w+ |
读取并写入文件,文件不存在则创建文件,存在则清空后写入。 |
wx+ |
和 w+ 类似,排他方式打开。 |
a |
追加写入,文件不存在则创建文件。 |
ax |
与 a 类似,排他方式打开。 |
a+ |
读取并追加写入,不存在则创建。 |
ax+ |
与 a+ 类似,排他方式打开。 |
文件读取
同步读取方法(readFileSync)
readFileSync
有两个参数:
- 第一个参数为读取文件的路径
- 第二个参数为
options
,默认值为null
,其中有encoding
(编码,默认为null
)和flag
(标识位,默认为r
),也可直接传入encoding
; - 返回值为文件的内容,如果没有
encoding
,返回的文件内容为Buffer
,如果有按照传入的编码解析。
1 | var fs = requere('fs'); |
异步读取文件(readFile)
异步读取方法 readFile
与 readFileSync
的前两个参数相同,最后一个参数为回调函数,函数内有两个参数 err
(错误)和 data
(数据)
- 当正常读取时,
err
参数为null
,data
参数为读取到的String
。 - 当读取发生错误时,
err
参数代表一个错误对象,data
为undefined
。
这也是Node.js标准的回调函数:第一个参数代表错误信息,第二个参数代表结果
1 | ; |
文件写入
同步写入(writeFileSync)
writeFileSync
有三个参数:
- 第一个参数为写入文件的路径或文件描述符;
- 第二个参数为写入的数据,类型为
String
或Buffer
; - 第三个参数为
options
,默认值为null
,其中有encoding
(编码,默认为utf8
)、flag
(标识位,默认为w
)和mode
(权限位,默认为0o666
),也可直接传入encoding
。
1 | fs.writeFileSync('a.txt','hello world'); |
异步写入(writeFile)
异步写入方法 writeFile
与 writeFileSync
的前三个参数相同,最后一个参数为回调函数,函数内有一个参数 err
(错误),回调函数在文件写入数据成功后执行。
1 | fs.writeFile("2.txt", "Hello world", err => { |