一、核心模块-文件读写

  • 核心模块
    就是nodejs自带的模块,在安装完nodejs之后,就可以任意使用啦。相当于学习js时使用的Math对象一样
  • 自定义模块
    程序员自己写的模块。相当于我们在学习js时的自定义函数
  • 第三方包
    其他程序员写好的模块,nodejs生态提供了一个专门的工具npm来管理第三方模块,例如我们前面学习的
    artTemplate等
const fs = require("fs");

二、文件读写综合案例

1、fs模块异步读取文件

路径:

  1. 同步与异步的概念理解
  2. fs.readFile异步读取文件基本写法
  3. fs.readFile异步读取图片
  4. 观察并处理错误

2、同步与异步的概念理解

  • 同步:多个功能按先后顺序执行,后面任务等待前面任务执行完毕后才会执行。如平常大家讨论问题时说:让我说完,意思是说我说完你再说。优缺点:如果前面任务执行太久会阻止后面任务的执行,降低程序执行性能,造成用户体验差,优点是编程方式简单,便于理解执行过程。
  • 异步:和同步相反,也就是在发出一个功能调用时,不管没有没得到结果,都继续往下执行。就像两个人吵架一样,各说各的,不管对方有没有说完。优缺点:不会造成阻塞,提升了程序执行性能,用户体验好,缺点是编程方式复杂,执行过程理解难度较大,会形成回调函数的嵌套。
  • 异步的表现形式:以一个回调函数的方式来实现异步任务的执行

3、fs.readFile异步读取文件基本写法

语法:

fs.readFile(path[, options], callback)

参数:path,读取文件的路径(相对路径或绝对路径)
options:读取文件的参数配置,通常用一个utf8字符串表示即可
callback:读取完毕的回调函数(err,data)=>{}

4、fs.readFile异步读取文件基本写法

场景一:
在一个js文件中编写代码,读取同级目录下的1.txt文件中的内容打印到小黑窗上
步骤:
① 在day01文件夹下 创建 /异步读取文件/rd.js 和 /异步读取文件/1.txt两个文件
② 在1.txt中随便输入一个字符串内容
③ 在rd.js中导入fs核心模块 const fs = require(‘fs’)
④ fs.readFile(‘./1.txt’,’utf8’,(err,data)=>{ consloe.log(data); })
⑤ 进入异步读取文件目录打开小黑窗,执行 node rd.js 看结果
注意:读取文本内容文件时,utf8参数要加上,不然打印出来的是一个Buffer二进制内容

// 1 引入文件读写模块 fs
const fs = require("fs");
// 2 调用 api 异步读取 文本文件 记得加上第二个参数  utf8 
fs.readFile("./1.txt", "utf8", function (err, data) {
  // 如果 读取失败 err 里面有值 否则读取成功 err 没有值
  if (err) {
    // 读取失败了  失败的一些错误处理
    console.log("失败");
    console.log(err);
  } else {
    // 读取成功了 正常输出即可
    console.log("成功");
    console.log(data);
  }
})

场景二:
在一个js文件中编写代码,读取同级目录下的1.jpg文件中的内容打印到小黑窗上
步骤:
① 在day01文件夹下 准备 /异步读取文件/rdimg.js 和 /异步读取文件/1.jpg 两个文件
② 在rdimg.js中导入fs核心模块 const fs = require(‘fs’)
③ fs.readFile(‘./1.jpg’,(err,data)=>{ consloe.log(data); })
④ 进入异步读取文件目录打开小黑窗,执行 node rdimg.js 看结果

const fs = require("fs");
// 读取图片 不需要加上 utf8 
fs.readFile("./img/pic.jpg", function (err, data) {
  if (err) {
    console.log("失败");
    console.log(err);
  } else {
    console.log("成功");
    console.log(data);
  }
})

小结:
fs.readFile(path,[,options],callback)语法中

  1. 异步读取文件方法的三个参数分别是什么作用?
    读取文件的路径,必填
    读取文件的编码,可选
    文件读取完毕后的回调函数必选,必填
  2. 其中在读取文本内容时,第二个参数通常指定什么?
    utf8,注意如果读取的是一个非文本内容文件时不需要指定第二个参数

5、异步读取文件处理错误

  • (err,data)=>{ } 中有两个参数
    参数1:err代表读取文件出错后的错误对象
    参数2:data代表读取文件成功后的内容,如果读取失败则data的值为为undefined
  • err参数特点:如果文件读取成功则err为null,如果读取失败则err存储的具体的错误信息对象
    通过如下if判断来处理错误
const fs = require("fs");
// 读取图片 不需要加上 utf8 
fs.readFile("./imgs/pic.jpg", function (err, data) {
  if (err) {
    console.log("读取文件失败");
    return; //阻止后面代码继续运行
  } else {
  	// 读取的数据
  	console.log(data);
    console.log("读取成功");
  }
})

6、fs模块同步读取文件

路径:

  1. fs.readFileSync同步读取文件基本写法
  2. fs.readFileSync同步读取图片
  3. 观察并处理错误

语法:

let res = fs.readFileSync(path[, options])

参数:
path,读取文件的路径(相对路径或绝对路径)
options:读取文件的参数配置,通常用一个utf8字符串表示即可

fs.readFileSync同步读取文件基本写法
场景一:
在一个js文件中编写代码,读取同级目录下的1.txt文件中的内容打印到小黑窗上
步骤:
① 在day01文件夹下 创建 /同步读取文件/rd.js 和 /同步读取文件/1.txt两个文件
② 在1.txt中随便输入一个字符串内容
③ 在rd.js中导入fs核心模块 const fs = require(‘fs’)
④ let res = fs.readFileSync(‘./1.txt’,’utf8’)读取到内容后直接返回,所以使用变量保存之
⑤ 进入同步读取文件目录打开小黑窗,执行 node rd.js 看结果

const fs = require("fs");
// 同步读取文件 
// fs.readFileSync("路径", "编码");
const res = fs.readFileSync("./1.txt", "utf8");
console.log(res);

场景二:
在一个js文件中编写代码,读取同级目录下的1.jpg文件中的内容打印到小黑窗上
步骤:
① 在day01文件夹下 准备 /同步读取文件/rdimg.js 和 /同步读取文件/1.jpg 两个文件
② 在rdimg.js中导入fs核心模块 const fs = require(‘fs’)
③ let res = fs.readFile(‘./1.jpg’) 读取到内容后直接返回,所以使用变量保存之
④ 进入同步读取文件目录打开小黑窗,执行 node rdimg.js 看结果
注意:读取文本内容文件时,utf8参数要加上,不然打印出来的是一个Buffer二进制内容

const fs = require("fs");
// 同步读取文件 
// fs.readFileSync("路径", "编码");
const res = fs.readFileSync("./1.jpg");
console.log(res);

使用try{}catch{}处理同步读取文件的错误

  • try catch语法: try{ 放有可能出错的代码 } catch(err){ 报错后执行的代码,通常是输出错误 }
  • 处理同步读取文件的错误
const fd = require("fs")
try{
	let res = fs.readFileSync("./1txt",'utf8')
	}catch(err){
		console.log("读取文件错误:"+err)
	}

7、fs.writeFile异步写入内容

语法:

fs.writeFile(path,data[, options], callback)

特点:writeFile方法是覆盖式写入,后面的内容会将前面的内容覆盖
参数:path,被写入文件的路径(相对路径或绝对路径)
data,要写入的内容,字符串格式
options:写入文件的参数配置,默认是utf8编码
callback:写入完毕的回调函数(err)=>{}

场景:在一个js文件中编写代码,将一段文本写入到同级目录下的1.txt文件中
步骤:
① 在day01文件夹下 创建 /异步覆盖写入文件/wd.js 和 /异步覆盖写入文件/1.txt两个文件
② 在wd.js中导入fs核心模块 const fs = require(‘fs’)
③ fs.writeFile(‘./1.txt’,’白日依山尽’,’utf8’,(err)=>{ consloe.log(‘写入成功’); })
④ 进入异步覆盖写入文件目录打开小黑窗,执行 node wd.js 看结果

const fs = require('fs');
// 异步
fs.writeFile("./1.txt", '白日依山尽', function (err) {
  if (err) {
    console.log("写入文件失败");
    console.log(err);
  } else {
    console.log("写入文件成功");
  }
})

8、fs.writeFileSync同步写入内容

语法:

fs.writeFileSync(path,data[, options])

特点:writeFile方法是覆盖式写入,后面的内容会将前面的内容覆盖
参数:path,被写入文件的路径(相对路径或绝对路径)
data,要写入的内容,字符串格式
options:写入文件的参数配置,默认是utf8编码

场景:
在一个js文件中编写代码,将一段文本写入到同级目录下的1.txt文件中
步骤:
① 在day01文件夹下 创建 /同步覆盖式写入文件/wd.js 和 /同步覆盖式写入文件/1.txt两个文件
② 在wd.js中导入fs核心模块 const fs = require(‘fs’)
③ fs.writeFileSync(‘./1.txt’,’白日依山尽’,’utf8’ })
④ 进入同步覆盖式写入文件目录打开小黑窗,执行 node wd.js 看结果
注意:同步写入方法返回值为:undefined

const fs = require('fs');
// 同步
fs.writeFileSync("./1.txt", '白日依山尽', function (err) {
  if (err) {
    console.log("写入文件失败");
    console.log(err);
  } else {
    console.log("写入文件成功");
  }
})

9、fs.appendFile异步追加内容

语法:

fs.appendFile(path,data[, options], callback)

特点:appendFile方法是追加式写入,后面的内容不会将前面的内容覆盖,只会追加到后面
参数:path,被写入文件的路径(相对路径或绝对路径)
data,要写入的内容,字符串格式
options:写入文件的参数配置,默认是utf8编码
callback:写入完毕的回调函数(err)=>{}

场景:
在一个js文件中编写代码,将一段文本追加到同级目录下的1.txt文件中
步骤:
① 在day01文件夹下 创建 /异步追加写入文件/wd.js 和 /异步追加写入文件/1.txt两个文件
② 1.txt中默认输入一段文本:白日依山尽
③ 在wd.js中导入fs核心模块 const fs = require(‘fs’)
④ fs.appendFile(‘./1.txt’,’黄河入海流’,’utf8’,(err)=>{ consloe.log(‘追加成功’); })
⑤ 进入异步追加写入文件目录打开小黑窗,执行 node wd.js 看结果

const fs = require("fs");
// 文件追加 异步
fs.appendFile("./assets/1.txt", "2222", function (err) {
  if (err) {
    console.log("出错");
    console.log(err);
  } else {
    console.log("成功");
  }
})

10、fs.appendFileSync同步追加内容

语法:

fs.appendFileSync(path,data[, options])

特点:appendFileSync方法是追加式写入,后面的内容不会将前面的内容覆盖,只会追加到后面
参数:path,被写入文件的路径(相对路径或绝对路径)
data,要写入的内容,字符串格式
options:写入文件的参数配置,默认是utf8编码

场景:在一个js文件中编写代码,将一段文本追加到同级目录下的1.txt文件中
步骤:
① 在day01文件夹下 创建 /同步追加写入文件/wd.js 和 /同步追加写入文件/1.txt两个文件
② 1.txt中默认输入一段文本:白日依山尽
③ 在wd.js中导入fs核心模块 const fs = require(‘fs’)
④ fs.appendFileSync(‘./1.txt’,’黄河入海流’,’utf8’)
⑤ 进入同步追加写入文件目录打开小黑窗,执行 node wd.js 看结果

const fs = require("fs");
// 文件追加
fs.appendFileSync("./1.txt", "黄河入海流","utf8");

总结

  1. 异步读取文件: fs.readFile(path,utf8编码,回调函数)
  2. 同步读取文件:fs.readFileSync(path,utf8编码)
  3. 异步写入内容:fs.writeFile(path,content,utf8,回调函数)
  4. 同步写入内容:fs.writeFileSync(path,content,utf8)
  5. 异步追加内容:fs.appendFile(path,content,utf8,回调函数)
  6. 同步追加内容:fs.appendFileSync(path,content,utf8)
  7. readFile的回调函数:(err,data)=>{}
  8. readFileSync没有回调函数,结果直接返回
  9. writeFile和appendFile的回调函数(err)=>{}
  10. writeFileSync和appendFileSync没有回调函数,结果返回undefined

案例

描述一:请把json文件的数据的按男女分别保存在一个Json文件里
JSON文件

[
  {
    "name": "路飞",
    "gender": "男"
  },
  {
    "name": "乔巴",
    "gender": "男"
  },
  {
    "name": "娜美",
    "gender": "女"
  },
  {
    "name": "罗宾",
    "gender": "女"
  }
]
const fs = require("fs");
// 1 读取 本地文件 读取成功了 数据也是 数组!! 
const heroListStr = fs.readFileSync("./assets/hero.json", "utf8");
// 2 将字符串 转成数组格式
const heroList = JSON.parse(heroListStr);
const manList = heroList.filter(item => item.gender === "男");
const womenList = heroList.filter(item => item.gender === "女");
// 生成男.json
fs.writeFileSync("./male.json", JSON.stringify(manList));
// 生成女.json
fs.writeFileSync("./female.json", JSON.stringify(womenList));

描述二:创建一个index.html文件,用node.js的数据替换html指定内容生成一个新的页面

const fs = require("fs");
// 获取要处理的数据 字符串  读取文件来获取
let html1 = fs.readFileSync("./assets/index.html", "utf8");
const obj = {
        title: "自己的页面",
        name: "大大的标题"
    }
    // 替换 {{title}}
html1 = html1.replace("{{title}}", obj.title);
html1 = html1.replace("{{name}}", obj.name);
fs.writeFileSync("./assets/index2.html", html1);

三、核心模块-路径处理(__dirname)

path是node的核心模块之一

作用:用来处理路径的拼接,分析,取后缀名

API列表:

nodejs 将项目中的文件夹放入node_modules中_node.js


快捷测试: 在任意一个小黑窗中 输入 node回车,进入到node执行环境,输入path.方法带上参数即可进行测试__dirname:

获取js文件在node中执行时的绝对路径

应用:

将相对路径的参照固定以js文件所在的绝对路径为参照,使用path.join()将1.txt拼接成一个绝对路径

nodejs 将项目中的文件夹放入node_modules中_es6_02


改造代码:

nodejs 将项目中的文件夹放入node_modules中_后端_03

const fs = require("fs");
// 路径处理模块
const path = require("path");
// const url = __dirname + "/assets/1.txt";
// 工作比较常用和常见的 处理路径的写法!! 严谨!! 
const url = path.join(__dirname, "assets", "1.txt");
console.log(fs.readFileSync(url, "utf8"));

四、服务器相关概念

1、服务器与客户端

  • 服务器
    提供网络服务的一台机器,通过在自己的电脑上安装特殊的软件(或者是运行某段特殊的代码)来提供服务,简单来说:服务器 = 电脑 + 能给其它电脑提供服务的软件。
  • 客户端与服务器
    提供服务的是服务器,享受服务的是客户端

2、服务器的类型

根据服务不同,服务器的类型也不同,也就是提供服务的软件也不同

  • web服务器(重点学习)
    安装apache/tomcat/iis或者在nodejs环境写代码来提供:图片/视频/音频浏览/新闻数据浏览等服务的服务器
  • ftp服务器
    安装serv-U软件,为其它电脑提供文件下载,共享服务
  • 数据库服务器
    安装mysql软件,为其它电脑提供数据库服务

3、web服务器

  • 用户通过浏览器来享受web服务器提供的图片,视频,音频等网页内容浏览的服务
  • 用户用url地址来访问某个web服务器上的资源
  • 浏览器端发起请求,web服务器收到请求后,响应这个请求,并将处理结果返回给浏览器
  • 浏览器端与web服务器是通过http(或者是https)协议来进行请求和响应的

4、IP地址

  • 全称:Internet Protocol Address(IP)
  • 作用:标识一个网络设备(计算机、手机、电视)在某一个具体的网络当中的地址,要访问某个电脑上的资源,先要找到它的ip
  • 在同一个网络中,计算机的IP是不允许相同的,都是唯一的
  • IP分类:IPV4(互联网协议第6版)、 IPV6(互联网协议第6版)
  • IPV4格式:[0-255].[0-255].[0-255].[0-255] 即为四个 0-255 的数字组成
    例如:127.0.0.1(本机访问) 或 192.168.106.2(局域网访问) 或 220.181.38.149(外网访问)
  • IPV6格式:X:X:X:X:X:X:X:X,每个X 以十六进制表示
    例如:FF01:0:0:0:0:0:0:1101 → FF01::1101,可以把连续的一段0压缩为“::”

5、域名

  • 域名:ip地址的别名
  • 由于ip地址不好记忆,我所以给它们取个好记的别名
  • 127.0.0.1 的别名为 localhost,系统自动解析的,不需要做额外的配置
  • 220.181.38.149的别名为 www.baidu.com,需要域名解析系统把域名翻译成IP地址,需要额外购买和配置

6、端口

  • 理解:如果理解IP地址(一台服务器)是一栋大商场,端口就是商场中的商铺的编号
  • 一个网络设备可以有65536个端口,范围是从[0,65535])
  • 不同的端口被不同的软件占用,以提供不同的服务
  • 服务器要提供服务必须要通过指定的端口
    -客户端与服务器都需要通过特定端口要进行通信(http://157.122.54.189:9092)
  • 端口是可以编程分配
  • 有一些端口号是被预定了的
  • http: 80
  • https:443
  • mysql:3306

7、HTTP协议

  • 协议:制定客户端与服务器之间的通讯规则,不同的协议的作用也不同,我们主要了解HTTP协议
  • http协议
    (1)定义:HTTP(HyperText Transfer Protocol) 超文本传输协议,浏览器与web服务器都要遵守的协议
    (2)HTTP 协议中明确规定了请求数据和响应数据的格式(报文)
  • 浏览器 请求 资源 要遵守 http 协议: 请求报文(请求行,请求头,请求体)
  • 服务器 返回 资源 要遵守 http 协议: 响应报文(响应行,响应头,响应体)

五、核心模块Http实现一个Web服务器

① 引入http核心模块

② 使用createServer来创建服务

③使用listen来启动服务,端口为8001(端口可以修改 0 - 65535)

④ 在浏览器输入http://127.0.0.1:8001回车即可看到服务器响应回来的信息:OK

也可以通过ipconfig查看你的本机ip,通过 http://局域网ip:8001回车访问

nodejs 将项目中的文件夹放入node_modules中_javascript_04

// 1 引入核心模块 http
const http = require("http");
// 2 创建一个服务器  返回一个服务器对象
const app = http.createServer(function (request, response) {
  // request 表示 接收用户的请求   请求的url 请求的类型 请求的参数 
  // response 表示  返回给用户的响应 返回用户什么数据 html标签 json 
  response.end("hello");
});
// 3 指定监听  开启哪个端口 提供服务
app.listen(8000, () => {
  console.log("端口开启成功 8000端口");
});

1、工作原理

使用http模块在本机上创建一个Web服务器,它来接收浏览器的请求,并给出响应。

nodejs 将项目中的文件夹放入node_modules中_es6_05

2、Http模块创建Web服务器代码解析

  • 引入核心模块require(‘http’),得到的http是一个对象
  • http.createServer方法创建一个http服务
    createServer方法参数是一个回调函数:当有http请求进来时,它会自动被调用,请求一次,它就被调用一次
    req参数:客户端的请求相关数据
    res参数:设置对本次请求的响应相关数据
  • server.listen() 用来监听端口
    如果监听成功,则回调函数会执行一次。
    如果不成功(例如端口被占用),会报错。

3、res.end()设置响应体

  • 语法:res.end(响应的数据)
    end()只能传入buffer或者是String类型的数据
  • 作用:设置响应体并结束本次请求
  • 用法:在createServer的回调函数中使用
const app = http.createServer((req, res) => {
  res.end("OK");
});
  • 注意:一次请求只能有一个res.end()响应,多个以第一个响应的数据为准,同时服务器报错终止

4、res.setHeader()设置响应头解决中文乱码

  • 作用:设置响应头信息,控制浏览器的一些行为
  • 语法:res.setHeader(响应头,响应值),两个参数的具体值都是http协议规定的
  • 用法:在createServer的回调函数中使用
  • 注意:
    ① res.setHeader()在res.end()之前才有效
    ② res.setHeader()可以设置多次
  • 应用举例:解决响应中文字符在浏览器显示成乱码问题
    res.setHeader(“Content-Type”,”text/html;charset=utf8”):
const app = http.createServer((req, res) => {
  res.setHeader("Content-Type", "text/html;charset=utf8");
  res.end("OK");
});

5、res.statusCode设置状态码

  • 场景:浏览器输入了一个不存在的url,则服务器返回404状态码
  • 语法:res.statusCode = 状态码,状态码是http协议规定的
    状态码: 500 (服务器异常) 404(资源找不到)
  • 注意:res.statusCode只有在res.end()前执行才有效

6、req.url

  • 通过 req.url来获取当前请求的url路径
  • req.url在哪儿?

7、req.url具体用法和效果

  • 代码
  • 不同的请求url通过req.url获取的结果

8、修改了服务器的代码要重启

  • 修改了服务器的代码要重启
  • 场景:更改res.end()的内容,重启后,再次观察是否有更新
    停止服务: 在小黑窗中按下ctrl+c 停止服务
    重启服务:就是重新运行程序(按下向上的箭头,再回车)

六、Web服务器对静态资源的解析响应

1、URL地址的组成

nodejs 将项目中的文件夹放入node_modules中_es6_06

2、URL格式

URL格式为: 协议://主机地址[:端口]/路径?查询字符串#锚点

  • 协议: http 或者是 https
  • 主机地址: IP地址 或者 域名
  • 端口号: http默认端口80,https默认端口443,默认端口可以省略不写
  • 路径:服务器文件夹上的资源。(.html/.css/.images/.js/接口)
  • 参数(查询字符串):问号后面的部分,是键值对的形式
  • 锚点: #后面表示 网页内部的锚点链接

3、静态资源

  • 静态资源一般表现为一个一个的文件。例如index.html, style.css, index.js, mp4, .png…
  • 处理请求静态资源时,服务器一般就直接读出资源的内容,再返回给客户端浏览器

4、不同的URL返回不同资源思路分析

  • 场景:用户在访问服务器上不同的url时,能返回不同的内容
  • 思路:在服务器端收到客户端发的请求之后,分析url是什么,然后分别对应处理

    实现:
  • 准备目录结构
  • 在server.js中通过http模块开启web服务器,端口监听8001
  • 在createServer的回调函数中通过req.url获取不同请求路径完成不同文件读取后响应给浏览器
  • 浏览器输入不同url进行效果查看

5、content-type作用

在http协议中,content-type用来告诉对方本次传输的数据的类型是什么

  • 在请求头中设置content-type来告诉服务器,本次请求携带的数据是什么类型的
  • 在响应头中设置content-type来告诉浏览器,本次返回的数据是什么类型的
  • res.setHeader方法可以设置content-type这个响应头,浏览器根据不同类型做出不同解析
    ※ 请求头和响应头都可以设置content-type

常见的几种文件类型及content-type

  • content-type类型查询地址
  • 常见的几种文件类型及content-type
    .html:res.setHeader(‘content-type’, ‘text/html;charset=utf8’)
    .css:res.setHeader(‘content-type’, ‘text/css;charset=utf8’)
    .js:res.setHeader(‘content-type’, ‘application/javascript’)
    .png:res.setHeader(‘content-type’, ‘image/png’)
    json数据:res.setHeader(‘content-type’, ‘application/json;charset=utf-8’)
    ※ 如果读取.html的文件内容,但是content-type设置为了text/css则浏览器将不会当作是html页面来渲染了

6、.html文件中的二次请求

  • 二次请求
    浏览器从服务器获取html文件之后,如果这个html文件中还引用了其它的外部资源(图片,样式文件等)
    则浏览器会重新再发请求给服务器获取这些资源

7、批量处理.html中的二次请求

  • 把所有的静态资源(.html,.png,.css,.js)全放在一个指定的目录public中
  • 收到用户的请求之后,去public目录下去找对应的文件
    找到,把内容读出来返回给用户
    找不到,报404
  • 目录如下:
    |-public
    |-public/index.html
    |-public/style.css
    |-public/01.html
    |-server.js
    在上面的目录结构中,我们把所有的静态资源全放在public下面,然后使用server.js来启动web服务器。

七、Web服务器处理接口响应

1、静态资源与接口

  • 静态资源
    它们一般表现为一个一个的文件。例如index.html, style.css, index.js, mp4, .png…
    处理请求静态资源时,服务器一般就直接读出资源的内容,再返回给客户端浏览器
    对于静态资源,我们请求方式是get请求
  • 动态资源:接口
    接口不是以某个具体的文件存在的,而是服务器上的一段代码
    访问接口时,服务器会执行这段代码,然后把代码的执行结果返回给客户端浏览器
    对于动态资源,我们常用的请求方式是get和post请求

2、接口请求方式

  • 发送接口请求的类型
    get:在地址栏中直接访问这个url就是get方式。
    post:通过表单提交,可以设置$.ajax的type为post
  • web服务器通过req.method获取当前请求的类型

3、接口的各种表现形式

get请求不带参数的接口: http://127.0.0.1:8003/getHero
get请求带参数的接口: http://127.0.0.1:8003/getHero?heroName=后羿
post请求接口 http://127.0.0.1:8003/addHero (参数在请求报文体中传输)

4、不带参数的接口

  • 场景:在server.js中写代码,提供一个名为getHero的Get接口(http://127.0.0.1:8003/getHero)它以json字符串格式返回db/data.json的内容
  • 步骤:
    ① 在server.js中使用http创建一个web服务器,端口为8003
    ② 在createServer的回调函数中通过fs.readFileSync读取db/data.json中的内容
    ③ 使用res.end()将json字符串响应会客户端浏览器
    ④ 增加url和method判断完成/getHero路径的get请求限定

5、带参数的Get接口

  • 场景:在server.js中写代码,提供一个名为getHero的Get接口(http://127.0.0.1:8003/getHero?name=xxx)它以json字符串格式返回db/data.json的name为xxx的内容
  • 前置知识:
    get请求的参数是附加在url后面
    URLSearchParams 解析参数
  • 场景:在server.js中写代码,提供一个名为getHero的Get接口(http://127.0.0.1:8003/getHero?name=xxx)它以json字符串格式返回db/data.json的name为xxx的内容
  • 步骤:
    ① 在server.js中使用http创建一个web服务器,端口为8003
    ② 在createServer的回调函数中解析出url?后面的参数值,通过URLSearchParams解析出参数值
    ③ 通过fs.readFileSync读取db/data.json中的内容,并通过filter方法过滤出名称为xxx的数据
    ④ 使用res.end()将json字符串响应回客户端浏览器

6、URLSearchParams 解析参数

URLSearchParams可以将查询字符串解析成一个对象,通过get方法获取到指定参数值
参考网址:点击查看
查询字符串格式: name=后裔&age=20
示例

let query = 'name=后裔';
// 通过urlSearchParams解析数值
let urlSearch = new URLSearchParams(query);
// 通过get方法获取到查询字符串name参数的值
let namevalue = urlSearch.get('name');

7、POST接口

  • 场景:在server.js中写代码,提供一个名为add的接口(http://localhost:8083/add),它以post的方式请求接口,并传入name和skinname值,把数据保存到db/data.json中去。
  • 前置知识
    ①post请求参数在请求体中,内容比较大(上传图片,上传文件…)
    ②后端是一段一段接收数据的,并不像get在请求行中传递的数据:直接写在url中的查询字符串内,可以立即通过req.url来解析出来
    ③在接收参数的过程中,会涉及req对象的两个事件data,end
    data事件,每次收到一部分参数数据就会触发一次这个事件。
    end事件,全部的参数数据接收完成之后会执行一次。
  • 在接收参数的过程中,会涉及req对象的两个事件data,end
    data事件,每次收到一部分参数数据就会触发一次这个事件。
    end事件,全部的参数数据接收完成之后会执行一次。
  • nodejs 将项目中的文件夹放入node_modules中_es6_07

  • 场景:
    在server.js中写代码,提供一个名为add的接口(http://localhost:8083/add),它以post的方式请求接口,并传入name和skinname值,把数据保存到db/data.json中去。
    步骤:
    在server.js中使用http创建一个web服务器,端口为8083
    在createServer的回调函数中通过data和end事件获取post请求体中的参数
    通过fs.writeFileSync将数据写入到/data/hero.json中
    使用res.end()将成功或失败的结果响应回浏览器
    使用postman进行接口测试
const http = require("http");
const fs = require("fs");
const app = http.createServer((req, res) => {
  if (req.method === "POST") {
    let result = "";
    req.on("data", chunk => result += chunk);
    req.on("end", () => {
      console.log(result); // cname=aaa&skin_name=bbb 
      const usp = new URLSearchParams(result);
      const hero = {
        cname: usp.get("cname"),
        skin_name: usp.get("skin_name"),
        id: Date.now()
      }
      // 获取本地文件 
      const data = fs.readFileSync("./data/hero.json");
      const list = JSON.parse(data);
      list.push(hero);

      fs.writeFileSync("./data/hero.json", JSON.stringify(list));
      res.end("添加成功");
    });
  } else {
    res.statusCode = 404;
    res.end("找不到")
  }
});

七、模块化的作用讲解

1、模块的作用

能够对一类功能做很好的分类管理

能够保护成员不被污染

不用考虑导入顺序

按需导入,可以随时更换模块,维护方便

nodejs 将项目中的文件夹放入node_modules中_后端_08

2、模块化的发展

  • 之前
    es5不支持模块化,让前端人员很为难;
    为了让es5支持模块化,我们一般会借用第三方库来实现:
    sea.js
    require.js
  • 现在
    es6原生语法也支持模块化(并不表示浏览器也直接支持模块化 — 需要单独设置一下)
    Nodejs内部也支持模块化(与es6的模块化有些不同之处),具体的语法在后面来介绍。

八、自定义模块的导出和导入

node.js中有三种模块:核心模块,自定义模块,第三方模块

1、基本语法规范

场景:使用自定义模块实现在index.js中使用tool.js中的加法函数

核心代码:

nodejs 将项目中的文件夹放入node_modules中_javascript_09


js文件名最好能够见名知意,例如,负责加减乘除运算的模块名称最好叫做 calc.js

自定义模块名称不能与核心模块同名,例如: fs.js 是不行的

模块中的成员可以通过module.exports关键字按需导出(想导出哪个由编码者决定)

使用固定关键字 require()导入模块,参数带有路径

2、两种导出方式的写法

在阅读其它人的代码时,可能会遇到这两种不同的写法。所以我们还是有必要了解一下的。

module.exports 关键字写法

exports 关键字写法

nodejs 将项目中的文件夹放入node_modules中_node.js_10

3、module.exports和export的关系

  • exports是module.exports的别名 exports === module.exports // 输出是 true
  • 初始exports和module.exports是指向同一块内存区域,其内容都是一个空对象
  • 如果在对象上添加属性两个对象的用法是一样的
// 1 mymodule.js
exports.f = function(){}
exports.pi = 3.145926

// 2 mymodule.js
exports.exports.f = function(){}
exports.exports.pi = 3.145926
  • 如果直接给对象赋值(例如:exports={a:1,b:2})exports和module.exports 就会不相等
  • 在引入某模块时:以该模块代码中module.exports指向的内容为准。

九、第三方包管理工具npm的使用

1、npm工具是什么及其作用

  • npm是node的包管理工具,它的出现是为了解决 Node中第三方包共享的问题
  • 当我们谈到npm时,我们在说两个东西:
    npm网站。这是一个第三方模块的"不花钱的超市",我们可以自由地下载,上传模块。
    npm包管理工具,帮助我们去npm网站上下载,上传第三方包
  • npm这个工具在安装node时,就会自动安装上
node-v

2、npm安装和使用包的基本用法

  • 场景:通过npm下载一个格式化日期包并使用它
    ① 创建一个新的空文件夹(注意命名不能是中文或者)
    注意:文件夹不能包含中文或者特殊字符
    如果之前已经初始化,则可以省略
    ② 执行npm init --yes 初始化package.json
    ③ 去npmjs.com网站 搜索 关键字 date 找到合适的格式化日期包
    ④ 按照文档完成下载(使用npm install 包名称 下载)
    ⑤ 通过require使用第三方包

3、npm init命令

在某个目录下开启小黑窗,输入npm init 最后生成一个package.json文件

npm init

如果你希望直接采用默认信息,可以使用:

npm init -y

说明:

  • 这个命令只需要运行一次,它的目的仅仅是生成一个package.json文件。
  • 如果项目根目录下已经有了package.json文件,就不需要再去运行这个命令了。
  • 这个package.json文件后期是可以手动修改的。

4、package.json文件

  • 它的整体内容是一个json字符串,用来对当前项目进行整体描述
    name: 表示这个项目的名字。如是它是一个第三方包的话,它就决定了我们在require()时应该要写什么内容。
    version:版本号
    keywords:关键字
    author: 作者
    descrption: 描述
    dependencies: 存放当前下载的包和版本,执行npm install 包 下载后自动保存到此节点

5、npm install 命令

  • 作用:npm install可以安装一个第三方包
  • 语法格式: npm install 第三方包 或 npm install 第三方包@版本号
  • 举例:
    npm install dayjs 安装最新版本
    npm install dayjs@1.10.5 指定安装版本 1.10.5

6、node_modules文件夹

  • 作用
    在使用npm install 命令时,会从npm网站下载对应的包,这些包的源代码会保存到这个文件夹中
  • 执行逻辑
    ① 当键入npm install XXX之后,这里假设这个XXX包是存在的,也没有出现任何的网络错误
    ② 当前目录如果没有node_modules文件夹则创建它
    ③ 下载XXX包保存到node_modules中,如果XXX还有其他依赖包也一并下载下来保存到node_modules中
  • 注意:我们在给别人分享代码的时候,通常会把node_modules文件夹排除,其他人拿到代码后,直接执行npm install回车后就会自动下载所有的包(会查找 package.json中保存好的所有包)

7、区分本地包和全局包

(1)本地安装(或者叫局部安装):
包安装在当前项目的根目录下(与package.json同级)的node_modules中
命令:npm install 包名
(2)全局安装:
包被安装到了全局的node_modules中
命令:npm install -g 包名 或者 npm install 包名 -g
(3)查看全局的node_modules路径:
npm root -g // 查看全局包的安装目录
npm list -g --depth 0 //查看全局安装过的包

全局安装的包:一般可提供直接在小黑窗执行的命令。我们通过对一些工具类的包采用这种方式安装,如:nodemon,nrm,yarn等。
本地安装的包:是与具体的项目有关的, 我们需要在开发过程中使用这些具体的功能。 如:前面用过的日期格式化包。
一个经验法则:要用到该包的命令执行任务的就需要全局安装, 要通过require引入使用的就需要本地安装。

8、全局包nodemon

(1)作用

  • nodemon:别人开发的一个第三方包,它能替代node命令去帮我们执行一个js文件,并自动检测到我们的代码如果有修改就会自动重新运行我们的代码
  • nodemon包地址:https://www.npmjs.com/package/nodemon

(2)用法
前置回顾:之前启动方式 node server.js
现在可以使用: nodemon server.js启动服务器
如何使用nodemon以及使用后的效果是什么:
① 全局安装nodemon: npm install -g nodemon 注意:此操作需要联网
② 进入server.js所在文件夹打开小黑窗执行 nodemon server.js即可启动服务器
③ 修改server.js 后nodemon会自动重启 server.js
注意: 默认情况下,nodemon会监控server.js同级目录下的任何内容发生改变都会导致重启,可以加上–ignore来排除一些文件不被监控 例如:忽略监控data.json文件,nodemon --ignore data.json server.js

(3)常见错误

nodemon运行 提示错误:无法加载文件…

nodejs 将项目中的文件夹放入node_modules中_javascript_11


解决办法

以管理员身份运行PowerShell

执行:get-ExecutionPolicy,回复Restricted,表示状态是禁止的

执行:set-ExecutionPolicy RemoteSigned

输入Y

9、全局包nrm

(1)作用:

  • nrm:别人开发的一个第三方包,可以帮助我们切换安装包的下载源地址
  • 为什么要切换包的下载源:
    因为下载包时,默认是从npm官网(国外的网站)下载,速度会比较慢,我们可以手动去切换安装来源为国内的地址,这样能加快下载速度。
  • nrm包的地址:https://www.npmjs.com/package/nrm

(2)用法
第一步: 全局安装
npm install nrm -g
第二步:列出所有的源信息
(*)标注的就是当前使用的源
使用 nrm ls 命令可以查看
第三步:根据需要切换源
使用 nrm use taotao 切换到taobao源
验证:此时使用npm install 下载包时就会去taobao源下载,由于在国内,下载速度会快一些

10、npm卸载包

  • 卸载包分为两种:本地包和全局包的卸载
  • 本地包卸载:
    进入到你想要卸载的包所在的文件夹,到package.json这一层即可
    打开cmd小黑窗
    在小黑窗中执行 npm uninstall 包名 简写: npm un 包名
    npm un 包名1 包名2
  • 全局包的卸载:
    在任意地方打开小黑窗
    输入 npm uninstall 全局包名 -g 简写:npm un 全局包名 -g
    npm un 包名1 包名2 -g

11、npm包从创建到发布

(1)npm发包到npmjs.com上

  • 场景:将本地开发的名为calc67的包发布到npmjs网站上
  • 前置操作:请先去npmjs.com上注册一个用户,并通过邮箱验证
  • 操作步骤:
    ① 项目初始化: 创建文件夹 calc67,小黑窗中输入:npm init --yes
    注意:文件夹名称不能是中文或带有特殊字符,
    通过 npm view calc67 检查一下npmjs上如果已经有calc65这个包了,则换一个名字
    ② 在calc67中创建一个calc.js文件并定义加法函数并导出(module.exports={add})
    ③ 切换当前npm源到npmjs上: nrm use npm
    ④ 连接npm: npm adduser (输入npmjs.com上注册时的用户名,密码,邮箱)
    ⑤ 把包上传到npm: npm publish
    ⑥ 上传成功验证:在小黑窗能看到 +calc67@1.0.0 表示成功
    ⑦ 通过 npm install calc67测试下载

(2)上传包出错的可能

  • 这个包名被别人先用了。
  • 包的版本号不对:每次publish时,包的版本号都应该要大于之前的版本号。
  • 文件过大。你可能需要创建.npmignore文件来设置在打包时要忽略哪些文件。如下是一个demo
    .npmignore文件中的内容
    /node_modules
    npm-debug.log
    /src
    /examples
    /build

(3)能够使用npm更新calc67这个包
修改calc.js代码,保存。
更新版本号。可直接在package.json中修改:只能改大,不能改小。
执行 npm publish完成更新
注意: npm publish执行前确保已经在小黑窗中通过adduser登录到了 npmjs.com上

(4)能够使用npm删除calc65这个包
① 在calc67这个文件里打开小黑窗
② 执行:npm unpublish 包名称 --force //强制删除
发布一个包24小时以内是不可以删除的,超过了24小时就允许删除了
注意:npm unpublish --force执行前确保已经在小黑窗中通过adduser登录到了 npmjs.com上

十、核心模块、自定义模块、第三方包的require规则

1、核心模块加载规则

加载核心模块的格式是 const xxx = require(“模块名”) ,如: require(‘fs’)

加载核心模块,直接从内存中加载,并缓存

同一个模块第一次require之后,就会缓存一份,下一次require时就直接从缓存中去取。

nodejs 将项目中的文件夹放入node_modules中_ajax_12

2、自定义模块加载规则

  • 如果require()中的参数是一个路径,则根据路径加载自定义模块,并缓存
const tool = require('./tool.js')
const tool1 = require('./tool.js')
consloe.log(tool === tool1) // true
  • require加载自定义模块,没有扩展名的情况下,查找文件顺序:
    以require(‘./main’) 为例
    先加载 main 文件
    如果没有再加载 main.js
    如果没有再加载 main.json,
    如果没有再加载 main.node(c/c++编写的模块)
    找不到就报错。

3、第三方模块加载规则

  • 加载第三方模块的格式是 const xxx = require(“模块名”) ,如:require(“date-format”) 并缓存
  • 以加载date-format这个第三方包为例node判断date-format不是核心模块,就会按照如下方式查找
    ① node 会去本级目录 node_modules下查找date-format模块
    ② 如果找不到,则查找上级目录node_modules下查找date-format模块
    ③ 直到查找到盘符根目录(例如:F:)下
    ④ 如果每一级目录都找不到就报模块找不到错误,如果在某一级目录找到了,则停止查找

十一、Express基本用法

1、使用Express创建web服务器基本步骤

① 先回顾使用nodejs创建服务器
② 使用Express创建服务器

// 1. 引入express框架
const express = require("express");
// 2. 通过构造函数创建服务器
const app = express();
// 3. 设置请求回调,express中有一个send方法可以响应数据,就算返回中文也不需要设置响应头,
//因为框架已经帮我们处理了
app.get("/", (req, res) =>{ res.send("你好,express"); } );
// 4. 监听8080端口
app.listen(8080);

其中1,2,4步是固定的,第3步根据具体需求来决定

2、接收Get 和 Post请求

Express给我们提供了非常方便的处理请求的方法
语法格式: app.method(‘请求路径’,回调函数)
举例:
① 接收get请求: app.get(‘/getlist,(req,res)=>{ res.send(‘响应内容’) })
② 接收post请求: app.post(’/update,(req,res)=>{ res.send(‘响应内容’)})
注意:express中建议大家使用send方法,因为它会自动根据内容决定响应Content-Type的类型
当然,之前的res.end()也是可以使用的

3、Express路由

路由格式

const app = express()
// 定义路由
app.METHOD(PATH,HANDLER)

app 是 express 实例 。(const app = express())

METHOD 是一个 HTTP 请求方法。 全小写格式。如:post,get,delete等

PATH 是请求路径

HANDLER 是当路由匹配到时需要执行的处理函数。(req,res)=>{ }

nodejs 将项目中的文件夹放入node_modules中_ajax_13

4、req对象

  • req.url : 获取请求url
  • req.method:获取请求方法
  • req.query: 获取url传入的查询字符串参数
    请求的url如果带有参数则会自动解析到query中,例如:/getHero?heroname=妲己
  • req.params : 获取url传入的路由参数
  • req.body:获取post请求体中的参数
    需要配合内置中间件完成 app.use(express.urlencoded()) 和 app.use(express.json())
  • res.send() : 作用类似于http模块中的res.end()
    举例:res.send(‘要响应的数据’) 它会自动增加content-type响应头,支持直接js对象参数作为响应数据
    res.send({name:“张三”})
  • res.json(): 直接将一个js对象或者数据以json字符串返回:res.json({name:“张三”})
  • res.status(): 设置响应状态码: res.status(404)
  • res.set() : 设置响应头
    res.set(‘content-type’,‘text/html;charset=utf8’)
    res.set(‘Access-Control-Allow-Origin’, “*”);

十二、Express处理get和post请求参数

1、GET方法获取参数

场景:假设访问URL为/getUser?name=tom 需要获取name的值
关键技术:可以通过req.query获取,res.query 是一个对象
代码如下:

// 访问路劲为/getUser?name=tom
app.get('/getUser',(req,res)=>{
	consloe.log(req.query)//输出{name:'tom'}
	res.send('获取到name参数的值为='+req.query.name)
})

案例:使用express实现获取英雄皮肤

需求:使用express 结合 data.json 完成如下两个要求
开启GET接口 通过 http://127.0.0.1:3001/getHeroSkin?heroName=后羿获取后裔的皮肤数据响应会客户端
分析:
① 需要使用express基本步骤开启web服务器,监听端口:3001
② app.get(‘/getHeroSkin’,(req,res)=>{ }) 定义get请求接口用于获取皮肤数据逻辑代码
③ 使用 res.set(‘Access-Control-Allow-Origin’, “*”); 完成允许CORS跨域设置
④ 使用req.query获取heroName参数值
⑤ 获取data.json中的数据完成过滤后res.send()响应回去

const express = requir('express');
const app = express();
 app.get('/getHeroSkin',(req,res)=>{
	 res.set('Access-Control-Allow-Origin', "*");
	 const { heroName } = req.query;
	 res.send(heroName)
});
app.listen(3001,()=>{
	consloe.log("开启成功,访问地址:http://127.0.0.1:3001/getHeroSkin");
));

2、POST方法获取参数

(1) 使用 express.urlencoded() 内置中间件来处理

场景:假设我们对/postdata发起post请求,请求参数也是txt=tom,如何获取txt参数的值?
步骤:
① 在express对象实例上app上注册urlencoded中间件:

app.use(express.urlencoded())

②使用req.body就可以获取到post请求体中的参数:

express.urlencoded()要和客户端的conent-type:applicaiton/x-www-form-urlencoded格式匹配

nodejs 将项目中的文件夹放入node_modules中_node.js_14


nodejs 将项目中的文件夹放入node_modules中_node.js_15

案例:使用express实现向data.json添加英雄皮肤

需求:使用express 结合 data.json 完成如下两个要求
开启POST接口通过 http://127.0.0.1:3001/addHeroSkin 将请求体数据{cname:’妲己’,skin_name:’妲己皮肤’} 添加到皮肤数据中
分析:
① 需要使用express基本步骤开启web服务器,端口:3001
② app.post(‘/addHeroSkin ’,(req,res)=>{}) 定义post请求接口,编写添加皮肤数据逻辑代码
③ 使用 res.set(‘Access-Control-Allow-Origin’, “*”); 完成允许CORS跨域设置
④ 通过req.body接收参数值,添加data.json中
⑤ 通过res.send()响应添加成功

const express = require('express')
const app = express()
const fs = require('fs')
 app.post('/addHeroSkin',(req,res)=>{
 res.set('Access-Control-Allow-Origin', "*");
 const data = req.body
 fs.writeFileSync("./hero.json", JSON.stringify(data));
    res.send('添加成功');
})
app.listen(3001,()=>{
console.log('Example app listening at http://localhost:3001')
})
(2)使用 express.json() 内置中间件来处理

场景:假设我们对/postdata发起post请求,请求参数{txt:‘张三’},如何获取txt参数的值?

步骤:

① 在express对象实例上app上注册json中间件:

app.use(express.json())

② 使用req.body就可以获取到post请求体中的参数

express.json()要和客户端的conent-type:applicaiton/json格式匹配

nodejs 将项目中的文件夹放入node_modules中_node.js_16

nodejs 将项目中的文件夹放入node_modules中_javascript_17

3、express.urlencoded() 和 express.json()

app.use(express.json())
app.use(express.urlencoded({ extended: true }))

十三、Express处理静态资源

1、使用Express托管

将右下角图中的public中的所有静态资源使用Express托管
只需一句代码就可以搞定了: express.static(‘public’)
具体使用:

// 加载express
const express = require('express')
// 调用express()得到一个app,类似于http.createServer()
const app = express();
// 设置请求对应的处理函数
app.use(express,static('public'))
// 监听端口号,启动Web服务
app.listen(3000,()=> return console.log('开启成功,访问地址:http://127.0.0.1:3000'))

此时,所有放在public下的内容可以直接访问
浏览器输入:http://127.0.0.1:3000/index.html 即可访问到index.html
注意,此时在url中并不需要出现public这级目录

2、添加限制前缀

将右下角图中的public中的所有静态资源使用Express托管-添加限制前缀
要求:浏览器输入:http://127.0.0.1:3000/static/index.html 才能可访问到index.html
关键代码:

// 限制访问前缀
app.use('/static',express.static('public'))

这意味着想要访问public下的内容,必须要在请求url中加上/static

nodejs 将项目中的文件夹放入node_modules中_后端_18


3、POST方法-文件上传中间件-multer

  • 步骤:
    打开multer文档
    安装 multer包:
npm install multer

根据文档进行使用,核心就三步

nodejs 将项目中的文件夹放入node_modules中_es6_19

  • multer.diskStorage方法 自定义文件存储路径和文件名
    destination:自定义文件存储路径
    filename:自定义文件存储名称

    4、理解接口传参
  • ajax请求服务器接口时content-type常见有三种取值:
  • express处理不同content-type的方案:

    5、路由中间件的使用
  • 使用场景:接口数量较多时,需要分类别管理,此时就需要用到路由中间件
  • 如下5组接口,并且每组接口都有特定的访问前缀
  • 用法:
const Router = express.Router() ;  // 定义路由对象
Router.get(‘/’,(req,res)=>{});   // 创建路径和对于的处理函数
app.use(Router);  // 全局使用    或者 app.use(‘/路径,Router)  // 局部使用
  • 实现思路
    ① 整理接口名。对众多的接口名进行整理和分类
    ② 通过nodejs的模块化(分别写在不同的文件中),分模块定义路由中间件,并导出
    ③ 在主文件中,导入并使用路由中间件

十四、Express中间件
1、理解
express中间件是一个特殊的url地址处理函数,一个 express 应用,就是由许许多多的中间件来完成的
作用

  • 执行任何代码。
  • 修改请求和响应对象。
  • 终结请求-响应循环(结束请求)。
  • 调用堆栈中的下一个中间件

    2、express中间件-语法格式
    中间件本质就是一个函数,它被当作 app.use(中间件函数) 的参数来使用
    定义格式
// 具名函数格式:
const handler = (req,res,next)={
	console.log(Data.now());
	next();
}
app.use(handler)

//匿名函数格式:
app.use((req,res,next)=>{
	console.log(Data.now());
	next();
})

req:请求报文对象
res:响应报文对象
next()作用:只有显示调用了next()才会进入到下一个中间件或者路由处理函数的执行,否则就到此为止

3、四种匹配规则

  • app.use(中间件)是应用级中间件,所有的请求都能匹配。
  • app.use(‘/apiname’,中间件) 。匹配请求路径是/apiname的请求。
  • app.get(‘/apiname’,中间件) 。匹配get类型并且请求路径是/apiname的请求,就是我们前面说的路由。
  • app.get(‘/apiname’,中间件1,中间件2) 。一个路由中使用多个中间件。

4、中间件分类

  • 应用级中间件
app.use((req,res,next)=>{})
app.get('/getlist',(req,res,next)=>{ },(req,res)={ })
  • 内置中间件
app.use(express.static('public'))
app.ues(express.erlencode())
app.use(express.json())
  • 路由级中间件
let router = express.Router()
router.get('/getlist',(req,res)=>{ })
app.use(router)
  • 错误处理中间件
app.use((err,req,res,next)=>{ })

错误中间件可以用来统一捕获当前请求处理过程中的一些异常
定义格式:

app.use((err,req,res,next)=>{
	console.error(err,stack)
	res.status(500).send('Something break')
})

nodejs 将项目中的文件夹放入node_modules中_ajax_20


注意: 错误中间件要定义在其他处理逻辑的后面(写到最后面)

  • 第三方中间件
multer  //文件上传

5、RESTful接口

RESTful API是目前比较成熟的一套互联网应用程序的API设计理论

REST本身并没有创造新的技术、组件或服务,REST指的是一组架构约束条件和原则

nodejs 将项目中的文件夹放入node_modules中_后端_21