初识Nodejs
将JavaScript运行在Nodejs中,使其可以用于后端开发
。
——如果写了一段js在浏览器运行,那么是作为前端;如果写了一段js在Nodejs中运行,那么是作为后端开发。
Nodejs基于V8引擎解析
和运行js代码。
Nodejs无法调用BOM
和DOM
等浏览器内置API
。Nodejs提供一些基础的API类似浏览器内置的API。
fs模块
官方提供的,用于操作文件的模块。它提供了一系列方法和属性,用来满足用户对文件操作的需求。
模块使用
导入模块
1 | const fs= require('fs') |
方法和属性
读取文件
1 | fs.readFile('1文件路径','编码格式',回调函数(失败后返回的结果,成功后返回的结果){执行的函数操作}) |
1 | //1 导入 |
写入数据
1 | fs.writeFile('1文件路径','2写入的内容','(3可选参数)数据编码格式',4回调函数(失败后返回的结果){执行的函数操作}) |
1 | const fs=require('fs') |
fs动态路径拼接问题
注意每次执行node
命令时,会以执行命令所在目录作为路径,这会影响文件中使用相对路径的代码。
如下:
1 | PS D:\Onedrive\NodejsWork\01 fs模块的使用> cd ../ |
解决方法:在代码中使用绝对路径
。
简易方法
使用__dirname
变量,可以获取当前文件所在目录的路径。
path模块
官方提供的用于处理路径的模块。
模块使用
1 | const path=requre('path') |
方法和属性
连接路径
用于连接路径。该方法的主要用途在于,会正确使用当前系统的路径分隔符,Unix系统是”/“,Windows系统是”"。
1 | path.join([path1][, path2][, ...]) |
1 | path.join('/a/b/c','../','d') |
获取文件名
1 | path.basename('路径'[, '需要被移除的后缀']) |
1 | const path=require('path') |
获取文件后缀名
1 | path.extname('文件路径') |
http模块
官方提供的用于创建web服务器
的模块,通过模块提供的http.createServer()
方法可以方便的创建一台web服务器,对外提供Web资源服务。
模块使用
1 | const http=require('http') |
Web服务器组成
- 引入 required 模块:我们可以使用 require 指令来载入 Node.js 模块。
- 创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
- 接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。
创建第一个简单的web服务器
例1
1 | //1 导入 |
例2
1 | // 引入 required 模块 |
request请求对象
绑定的requset方法中的回调函数,可以使用一个请求对象参数
1 | server.on('requset',function(req){ |
请求对象常用属性
1 | req.headers: 返回的是一个对象, 对象中包揽了所有的请求报文头 |
response响应对象
1 | //1 导入 |
响应对象常用属性
1 | res.write(): 发送数据 |
中文乱码问题
在使用res.end()
方法响应中文内容时乱码,可以尝试设置响应头res.setHeader('Content-Type','text/html;charset=utf-8')
。
根据不同url响应不同网页
1 | const http = require('http'); |
模块化
模块化是指在解决一个复杂问题时,自顶而下逐层将系统划分为若干模块的过程(化繁为简)。模块是可以组合、分解、更换的单元。
模块分类
内置模块
由Nodejs官方提供的,例如:fs、path、http等模块。
自定义模块
由用户创建的每个js文件,都是自定义模块。
第三方模块
非官方提供的模块。
模块的加载和创建方法
加载模块
1 | // 1. 内置模块和第三方模块 |
创建模块
自定义模块需要使用
module对象
在exports属性
中挂载成员,外部才能使用模块的成员。
模块作用域
与函数作用域相似,在自定义模块中定义的变量、函数等,只能在模块内访问,这种模块级别的访问限制叫作模块作用域。
作用域的优点
防止了全局变量污染。
全局变量污染
如上图所示,在两个js文件中都对username的值进行了定义,但最终输出在控制台的值为ls,这是因为第二个文件login.js在reg.js之后被引入,所以后来者覆盖了之前的值。
对外共享成员
module对象
存在于每个自定义模块中,它存储了当前模块的相关信息
。
1 | console.log(module) |
共享的方法
使用module对象的export属性共享模块中的成员
方法一 挂载属性和方法
1 | module.exports.属性='属性值' |
方法二 直接指向一个新对象
1 | module.exports={ |
exports对象
与module.exports指向同一个对象。用于简化书写。
用法于module.exports
相同。
建议不要混合使用。
使用注意
若将exports对象直接指向一个新对象,在使用require()导入时,则获取不到共享出去的成员了!
exports和module.exports的使用误区
虽然用法上相同,但是使用require()
方法导入模块时,永远得到的是module.exports
所指向的对象。
模块化规范 CommonJS
Nodejs遵循了CommonJS模块化规范,CommonJS中规定了模块的特性
和各模块之间如何依赖
。
CommonJS规定
- 每个模块内部,module变量代表当前模块。
- module变量是一个对象,它的exports属性是对外的接口。
- 加载某个模块,其实是加载模块的module.exports属性。require()方法用于加载模块。
npm和包
Nodejs中第三方模块又称为包。
包由第三方开发,免费使用。
Nodejs内置模块仅提供一些底层API,而包基于内置模块封装而来,提供更高级的API,极大的提高了开发效率。
使用npm工具下载包。
常用npm包
模块的加载机制
内置模块
优先从缓存中加载,不会反复执行require
方法。
内置模块的优先级高于自定义模块。
自定义模块
匹配自定义模块时Node会依次按照确切文件名
、补全.js
、补全.json
、补全.node
方式尝试导入。
第三方模块
首先查找当前目录下的node_modules\tools
,其次是上一级目录,再是用户目录下(C:\User\node_modules\tools
)、最后是node的安装目录下。
目录作为模块
- 查找package.json文件,寻找main属性值,作为required的入口
- 找不到package.json或没有main属性值或无法解析,则加载目录下的index.js文件
- 上面都失败了,则报错。
Node.js REPL(交互式解释器)
Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Windows 系统的终端或 Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应。
Node 自带了交互式解释器,可以执行以下任务:
- 读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。
- 执行 - 执行输入的数据结构
- 打印 - 输出结果
- 循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
Node.js 回调函数
Node.js 异步编程的直接体现就是回调。
异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。
回调函数一般作为函数的最后一个参数出现。
1 | function foo1(name, age, callback) { } |
阻塞代码
创建input文件,文件内容为
Hello world!
创建zusai.js文件,代码为
1 | var fs = require("fs"); |
非阻塞代码
创建feizusai.js,代码为:
1 | var fs = require("fs"); |
两者效果相同,但效率不同。
前者需要先读取文件后执行输出程序,后者同时进行。
事件驱动程序
监听事件触发操作
创建listenEvents.js
1 | // 引入 events 模块 |