- 前言
- 一 初始 Express
- 1 Express简介
- 1.1 什么是Express
- 1.2 Express能做什么
- 2 Express的基本用法
- 2.1 安装
- 2.2 创建基本的Web服务器
- 2.3 监听 GET 与 POST 请求
- 2.4 把内容响应给客户端
- 2.5 获取 URL 中携带的查询对象
- 2.6 获取 URL 中的动态参数
- 3 托管静态资源 (外界可以访问自己服务器资源)
- 3.1 托管一个目录 (express.static() 方法)
- 3.2 托管多个静态资源目录
- 3.3 挂载路径前缀
- 4 nodemon 工具
- 二 Express 路由
- 1 路由的概念
- 1.1 什么是路由
- 1.2 Express 中的路由
- 1.3 Express 中路由的例子
- 1.4 路由的匹配过程
- 2 路由的使用
- 2.1 最简单用法
- 2.2 模块化路由
- 2.3 创建路由模块
- 2.4 注册路由模块
- 2.5 为路由模块添加前缀
- 三 中间件
- 1 中间件的概念
- 1.1 什么是中间件
- 1.2 现实生活中的例子
- 1.3 Express 中间件的调用流程
- 1.4 Express 中间件的格式
- 1.5 next 函数的作用
- 2 Express 中间件的初体验
- 2.1 定义中间件函数
- 2.2 全局生效的中间件
- 2.3 定义全局中间件的简化形式 (2.1 和 2.2 的合体)
- 2.4 中间件的作用
- 2.5 定义多个中间件
- 2.6 局部生效的中间件
- 2.7 定义多个局部中间件
- 2.8 了解中间件的5个注意事项
- 3 中间件的分类
- 3.1 应用级别中间件
- 3.2 路由级别中间件
- 3.3 错误级别中间件
- 3.4 Express 内置中间件
- 3.5 第三方中间件
- 4 自定义中间件
- 4.1 需求描述与实现步骤
- 4.2 定义中间件
- 4.3 监听 req 的 data事件
- 4.4 监听 req 的 end 事件
- 4.5 使用 querystring 模块解析请求数据
- 4.6 将解析出的数据对象挂载为 req.body
- 4.7 将自定义中间件封装为模块
- 四 使用Express 写接口
- 1 创建基本的服务器
- 2 创建 API 路由接口
- 3 编写 GET 接口
- 4 编写 POST 接口
- 5 CORS 跨域资源共享
- 5.1 接口的跨域问题
- 5.2 使用 CORS 中间件解决跨域问题
- 5.3 什么是 CORS
- 5.4 CORS 的注意事项
- 5.5 CORS 响应头部 - Access-Control-Allow- Origin
- 5.6 CORS响应头部 - Access-Control-Allow- Headers
- 5.7 CORS响应头部 -Access-Control-Allow- Methods
- 5.8 CORS 请求分类
- 5.9 简单请求
- 5.10 预检请求
- 5.11 简单请求和预检请求的区别
- 6 JSONP 接口
- 6.1 回顾 JSONP 概念与特点
- 6.2 创建JSONP 接口的注意事项
- 6.3 实现 JSONP 接口的步骤
- 6.4 在网页中使用 JQuery 发起JSONP请求
前言
本文包含 Express框架 基本内容,参考于黑马教学视频通过自己理解整理,所以这是一篇用于小白新手入门,或者复习使用的笔记, 从最基础带你认识Express基本内容, 到可以独立封装自己的接口
如有做的不好的地方,敬请谅解,欢迎指出,持续更新改正
一 初始 Express 1 Express简介 1.1 什么是Express
官方: Express是基于Node.js平台,快速,开放,极简的Web开发框架
通俗理解: Express的作用和Node.js内置的http模块类似,专门用来创建Web服务器的
本质: 就是一个npm上的第三方包(基于http模块封装),提供了快速创建Web服务器的便捷方法
链接: Express中文官网
1.2 Express能做什么
前端最常见的两种服务器
- Web网站服务器: 专门对外提供Web网页资源的服务器
- API接口服务器: 专门为外提供API接口的服务器
使用Express,可以方便,快速创建Web网站的服务器或API接口服务器
2 Express的基本用法 2.1 安装
执行终端命令
npm i express@4.17.1
2.2 创建基本的Web服务器
// 1 导入express
const express = require('express')
// 2 创建web服务器
const app = express()
// 3 调用app.listen(端口号, 回调函数) 启动服务器
app.listen(80, ()=>{
console.log('express server running at http://127.0.0.1');
})
2.3 监听 GET 与 POST 请求
app.get() 和 app.post()
//参数1:客户端请求的URL地址
//参数2:请求对应的处理函数 req:请求对象 res:响应对象
app.get('请求URL', function(req, res) {处理函数}
//参数1:客户端请求的URL地址
//参数2:请求对应的处理函数 req:请求对象 res:响应对象
app.post('请求URL', function(req, res) {处理函数}
2.4 把内容响应给客户端
res.send() 方法
// 1 导入express
const express = require('express')
// 2 创建web服务器
const app = express()
// 4 监听客户端的GET和POST请求, 并向客户端响应内容
app.get('/user', function(req, res){
// 调用 res.send() 方法, 向客户端响应一个对象
res.send({name: 'zt', age: 20})
})
app.post('/user', function(req, res){
// 调用 res.send() 方法, 向客户端响应一个文本
res.send('请求成功')
})
// 3 调用app.listen(端口号, 回调函数) 启动服务器
app.listen(80, ()=>{
console.log('express server running at http://127.0.0.1');
})
2.5 获取 URL 中携带的查询对象
req.query
在请求时, 将查询字符串写到url后面, req.query 就能获取到
app.get('/', function(req, res){
// 通过req.query 可以获取到客户端发送过来的 查询参数, 默认情况下是空对象
res.send(req.query)
})
2.6 获取 URL 中的动态参数
req.params对象
可以访问到 URL 中, 通过 : 匹配到的动态参数
app.get('/user/:id', function(req, res){
// req.params 存放通过动态匹配过来的参数值, 默认是一个空对象
res.send(req.params)
})
假如 url 是user/1, 响应值如下
{
"id": "1"
}
注意
- 冒号后名称不固定, 合理合法就行
- 可以有多个动态参数
3 托管静态资源 (外界可以访问自己服务器资源) 3.1 托管一个目录 (express.static() 方法)
express.static() 方法, 非常方便地创建一个静态资源服务器
app.use(express.static('目录'))
注意: Express 在指定静态目录查找文件, 并对外提供资源访问路径, 因此, 存放静态文件的目录名不会出现在 URL 中
const express = require('express')
const app = express()
// 调用express.static(目录) 方法, 提供对外静态资源
app.use(express.static('./code'))
app.listen(80, ()=>{
console.log('express server running at http://127.0.0.1');
})
3.2 托管多个静态资源目录
只需多次调用 express.static() 函数
app.use(express.static('目录1'))
app.use(express.static('目录2'))
注意: 访问静态资源文件时, 会根据目录添加顺序查找
3.3 挂载路径前缀
可以通过如下方法, 为静态资源路径添加一个路径
qpp.use('前缀路径', express.static('目录'))
这样访问静态资源目录前必须加入 前缀路径
4 nodemon 工具
安装后, 当项目代码被修改, 就能够监听项目文件的变动, 修改后, 自动重启项目
npm i -g nodemon
以后不要node 启动项目, 直接用nodemon 启动
nodemon app.js
二 Express 路由 1 路由的概念 1.1 什么是路由
广义上说, 路由就是 映射关系
1.2 Express 中的路由
Express中, 路由是 客户端的请求 与 服务器处理函数 之间的映射关系
由三部分组成:
- 请求类型
- 请求的 URL 地址
- 处理函数
app.类型(URL地址, 处理函数)
1.3 Express 中路由的例子
app.get('/user:id', function(req, res){
res.send(req.params)
})
app.post('/user', function(req, res){
res.send('请求成功')
})
1.4 路由的匹配过程
一个请求到达服务器后, 需要先经过路由的匹配, 只有成功后, 才会调用对应的处理函数
匹配时, 会按照路由顺序匹配, 如果请求类型 和 请求URL同时匹配成功, 则会交给处理函数处理
注意:
- 按照定义的先后顺序进行匹配
- 请求类型和请求URL同时匹配成功, 才会调用对应的处理函数
2 路由的使用 2.1 最简单用法
最简单的用法就是最简单的 app.get() 和 app.post() 方法 把路由挂载在app上
app.get('/', function(req, res){
res.send('Hello World')
})
app.post('/', function(req, res){
res.send('Post Requset')
})
实际上用的不多, 因为代码体积太大
2.2 模块化路由
为了方便对路由进行模块化的管理, Express不建议将路由直接挂载到app上, 而是将路由抽离为单独的模块
步骤如下
- 创建路由模块(自定义模块)对应的 .js 文件
- 调用 express.Router() 函数创建路由对象
- 向路由对象上挂载具体路由
- 使用 module.exports 向外共享路由对象
- 使用 app.use() 函数注册路由模块
2.3 创建路由模块
// 1 导入 express
const express = require('express')
// 2 创建路由对象
const router = express.Router()
// 3 挂载具体的路由
router.get('/user/list', (req,res) =>{
res.send('Get user list')
})
router.post('/user/add', (req,res)=>{
res.send('Add new user')
})
// 4 向外导出路由对象
module.exports = router
2.4 注册路由模块
app.use() 函数的作用, 就是来注册全局中间件
什么是中间件, 不要着急, 马上会提到
const express = require('express')
const app = express()
// 1 导入路由模块
const router = require('./router')
// 2 注册路由模块
app.use(router)
app.listen(80, ()=>{
console.log('http://127.0.0.1');
})
2.5 为路由模块添加前缀
在调用 app.use() 函数, 参数前加一个前缀路径
app.use('路径前缀',router)
以后每次请求, 都需要加上前缀路径
三 中间件 1 中间件的概念 1.1 什么是中间件
中间件(Middleware) , 特指业务流程的中间处理环节
1.2 现实生活中的例子
处理污水, 一般经过三个处理环节, 从而保证达标
处理污水的环节, 就叫中间件
1.3 Express 中间件的调用流程
当一个请求到达 Express 的服务器后, 可连续调用多个中间件, 从而对这次请求进行 预处理
中间件就是用来预处理的
1.4 Express 中间件的格式
Express 的中间件, 本质上就是一个 function 处理函数, 只不过参数有些特殊
注意: 中间件的函数参数列表中, 必须包含 next 参数, 而路由处理函数中只包含 req 和 res
1.5 next 函数的作用
next 函数是实现多个中间件连续调用的关键, 表示把流转关系转交给下一个中间件或路由
2 Express 中间件的初体验 2.1 定义中间件函数
把流转关系, 转交给下一个中间件或路由 next()
const express = require('express')
const app = express()
// 定义一个最简单的中间件函数
const mw = function(req,res,next){
console.log('这是一个最简单的中间件');
// 把流转关系, 转交给下一个中间件或路由
next()
}
app.listen(80, ()=>{
console.log('http://127.0.0.1');
})
2.2 全局生效的中间件
app.user() 函数
客户端发起任何的请求, 到达服务器后, 都会触发中间件, 就叫全局生效的中间件
通过调用 app.use(中间件函数), 即可定义
// 将mw注册为全局生效的中间件
app.use(mw)
app.get('/',function(req, res){
res.send('Home page')
})
2.3 定义全局中间件的简化形式 (2.1 和 2.2 的合体)
app.use(中间件函数)
// 全局中间件的简写
app.use(function(req,res,next){
console.log('这是一个最简单的中间件');
// 把流转关系, 转交给下一个中间件或路由
next()
})
2.4 中间件的作用
多个中间件之间, 共享一份 req 和 res.
基于这样的特性, 可以在上游中间件中, 统一为 req 和 res 对象添加自定义的属性或方法, 供下游中间件或路由使用
// 中间件的作用
const express = require('express')
const app = express()
app.use(function(req,res,next){
// 获取到请求到达服务器的时间
const time = Date().now()
// 为req 对象, 挂载自定义属性, 把时间共享给后面路由
req.startTime = time
next()
})
app.get('/',function(req, res){
res.send('Home page' + req.startTime)
})
app.get('/user',(req, res)=>{
res.send('User page' + req.startTime)
})
app.listen(80, ()=>{
console.log('http://127.0.0.1');
})
2.5 定义多个中间件
可以使用 app.use() 连续定义多个全局中间件, 会按照中间件定义的先后顺序依次进行调用
const express = require('express')
const app = express()
// 定义第一个全局中间件
app.use((req, res, next) => {
console.log('调用第一个全局中间件');
next()
})
// 定义第二个全局中间件
app.use((req, res, next) => {
console.log('调用第二个全局中间件');
next()
})
app.get('/user', (req, res) => {
console.log('User page');
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
2.6 局部生效的中间件
不使用 app.use() 定义的中间件, 就叫局部生效的中间件
// 局部生效中间件
const express = require('express')
const app = express()
const mw1 = (req, res, next) => {
console.log('调用了局部生效中间件');
next()
}
// 将中间件函数放入局部生效
app.get('/', mw1, (req, res) => {
res.send('Home page')
})
app.get('/user', (req, res) => {
res.send('User page')
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
2.7 定义多个局部中间件
以下两种方式都可
app.get('/', mw1, mw2, (req, res) => {res.send('Home page')})
app.get('/', [mw1, mw2], (req, res) => {res.send('Home page')})
2.8 了解中间件的5个注意事项
- 一定要在路由之前注册中间件
- 客户端发送过来的请求, 可以连续调用多个中间件处理
- 执行完中间件的业务代码后, 不要忘记调用 next() 函数
- 为了防止代码逻辑混乱, 调用 next()函数后不要再写额外的代码
- 连续调用多个中间件时, 多个中间件之间, 共享 req 和 res 对象
3 中间件的分类
官方把常见的中间件用法分为五大类
- 应用级别
- 路由级别
- 错误级别
- Express 内置
- 第三方
3.1 应用级别中间件
通过 app.use() 或者 app.get() 或者 app.post() , 绑定到app实例上的中间件, 就叫应用级别中间件
3.2 路由级别中间件
绑定到 express.Router() 实例上的中间件
3.3 错误级别中间件
专门用来捕获整个项目中发生的异常错误, 防止项目异常崩溃的问题
错误级别的中间件的 处理函数中, 必须有四个参数, (err , req, res, next)
// 错误级别中间件
const express = require('express')
const app = express()
// 定义路由
app.get('/', (req, res) => {
// 人为制造错误
throw new Error('服务器内部发生错误!')
res.send('Home page')
})
// 定义错误级别中间件, 捕获错误
app.use((err, req, res, next) => {
console.log('发生了错误' + err.message);
res.send('Error' + err.message)
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
注意: 错误级别中间件, 必须注册在所有路由之后
3.4 Express 内置中间件
4.16.0 版本开始, 内置了三个常用中间件
- express.static 快速托管静态资源内置中间件 (无兼容性)
- express.json 解析 JSON 格式的请求体数据 (有兼容性 4.16.0以后支持)
- express.urlencoded 解析URL-encoded 格式请求体数据 (有兼容性 4.16.0以后支持)
演示 express.json 和 express.urlencoded
// 演示 express.json express.urlencoded
const express = require('express')
const app = express()
// 配置中间件解析
app.use(express.json())
app.use(express.urlencoded({extended: false}))
// 定义路由
app.post('/user', (req, res) => {
// 在服务器, 可以使用 req.body 属性, 来接收客户端发过来的请求体数据
// 默认情况, 不配置解析表单数据中间件, 则等于undefined
console.log(req.body);
res.send('ok')
})
app.post('/book',(req, res)=>{
console.log(req.body);
res.send('ok')
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
3.5 第三方中间件
非官方内置, 由第三方开发, 按需下载并配置
例如: body-parser这个第三方中间件, 使用步骤如下
- 运行 npm i body-parser 安装中间件
- 使用 require 导入中间件
- 调用 app.use() 注册并使用中间件
演示 body-parser
// 第三方中间件使用 body-parser
const express = require('express')
const app = express()
// 导入解析表单数据的中间件 body-parser
const parser = require('body-parser')
// 使用app.use() 注册中间件
app.use(parser.urlencoded({extended: false}))
app.post('/user',(req, res)=>{
console.log(req.body);
res.send('ok')
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
注意: Express 内置中间件 express.urlencoded , 就是基于 body-parser 这个第三方中间件封装的
4 自定义中间件 4.1 需求描述与实现步骤
手动模拟一个类似 express.urlencoded 这样的中间件, 解析POST提交的表单数据
步骤
- 定义中间件
- 监听 req 的 data 事件
- 监听 req 的 end 事件
- 使用 querystring 模块解析请求体数据
- 解析出来的数据对象挂载为 req.body
- 将自定义中间件封装为模块
4.2 定义中间件
// 定义自己的中间件
const express = require('express')
const app = express()
// 解析表单数据的中间件
app.use((req, res, next)=>{
// 定义中间件具体的业务
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
4.3 监听 req 的 data事件
需要监听 req 对象的 data事件, 获取客户端发送到服务器的数据
如果数据量比较大, 客户端会将数据切割后分批发送到服务器
所以 data 事件可能会触发多次, 每一次触发, 获得的数据只是完整数据的一部分, 需要手动拼接
// 定义一个 str 字符串 专门用来存储客户端发送过来的请求体数据
let str = ''
// 监听 req 的 data事件
req.on('data', (chunk) => {
str += chunk
})
4.4 监听 req 的 end 事件
当请求体数据接收完毕后, 会自动触发 req 的end事件
因此, 在end事件中, 拿到处理完整的请求体数据
// 定义自己的中间件
const express = require('express')
const app = express()
// 解析表单数据的中间件
app.use((req, res, next)=>{
// 定义中间件具体的业务
// 定义一个 str 字符串 专门用来存储客户端发送过来的请求体数据
let str = ''
// 监听 req 的 data事件
req.on('data', (chunk) => {
str += chunk
})
// 监听 req 的 end 事件
req.on('end', () => {
// 在str中存放的是完整的请求体数据
console.log(str);
// 把字符串格式的请求体数据, 解析成对象格式
})
})
app.post('/user',(req, res)=>{
res.send('ok')
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
4.5 使用 querystring 模块解析请求数据
Node.js 内置了一个 querystring 模块, 专门用来处理查询字符串.
通过这个模块提供的 parse() 函数, 可以把查询字符串, 解析成对象格式
// 导入内置的 querystring 模块
const qs = require('querystring')
// 把字符串格式的请求体数据, 解析成对象格式
const body = qs.parse(str)
4.6 将解析出的数据对象挂载为 req.body
上游中间件和下游中间件及路由之间, 共享一份 req 和 res .
将解析出来的数据, 挂载为 req 的自定义属性, 命名为 req.body 供下游使用
req.on('end', () => {
// 把字符串格式的请求体数据, 解析成对象格式
const body = qs.parse(str)
req.body = body
next()
})
最终定义完自己的中间件
// 定义自己的中间件
const express = require('express')
const app = express()
// 导入内置的 querystring 模块
const qs = require('querystring')
// 解析表单数据的中间件
app.use((req, res, next)=>{
// 定义中间件具体的业务
// 定义一个 str 字符串 专门用来存储客户端发送过来的请求体数据
let str = ''
// 监听 req 的 data事件
req.on('data', (chunk) => {
str += chunk
})
// 监听 req 的 end 事件
req.on('end', () => {
// 在str中存放的是完整的请求体数据
// 把字符串格式的请求体数据, 解析成对象格式
const body = qs.parse(str)
req.body = body
next()
})
})
app.post('/user',(req, res)=>{
res.send(req.body)
})
app.listen(80, () => {
console.log('http://127.0.0.1');
})
4.7 将自定义中间件封装为模块
把自己定义的中间函数放到一个新的js文件中, 利用原文件app.use() 添加即可
四 使用Express 写接口 1 创建基本的服务器
const express = require('express')
const app = express()
//此处写接口代码
app.listen(80, () => {
console.log('http://127.0.0.1');
})
2 创建 API 路由接口
//apiRouter.js 路由模块
const express = require('express')
const router = express.Router()
//此处写代码
module.exports = router
//--------------------------------------------------------------------------------
// app.js 导入并注册路由模块
const router = require('./apiRouter.js')
app.use('/api', router)
3 编写 GET 接口
router.get('/get', (req, res) => {
//获取到客户端通过查询字符串, 发送到服务器的数据
const query = req.query
//调用res.send() 方法, 把数据响应给客户端
res.send({
status: 0, //状态 0 表示成功, 1表示失败
msg: 'GET请求成功', //状态描述
data: query //需要响应给客户端的具体数据
})
})
4 编写 POST 接口
router.post('/post', (req, res) => {
//获取到客户端通过请求体, 发送到服务器的URL-encoded数据
const body = req.body
//调用res.send() 方法, 把数据响应给客户端
res.send({
status: 0, //状态 0 表示成功, 1表示失败
msg: 'POST请求成功', //状态描述
data: body //需要响应给客户端的具体数据
})
})
注意: 如果需要获取 URL-encoded 格式的请求体数据, 必须配置中间件 app.use(express.urlencoded({extended: false}))
5 CORS 跨域资源共享 5.1 接口的跨域问题
控制台出现 Access-Control-Allow-Origin 就是存在跨域问题
有两种解决方案:
- CORS (主流)
- JSONP (有缺陷, 只支持GET请求)
5.2 使用 CORS 中间件解决跨域问题
CORS是 Express 中的第三方中间件, 通过安装配置 CORS 中间件, 可以方便地解决跨域问题
步骤 :
- 运行 npm i cors 安装中间件
- 使用 require 导入中间件
- 在路由之前调用 app.use(cors()) 配置中间件
5.3 什么是 CORS
CORS 由一系列 HTTP 响应头 组成, 这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码跨域获取资源
浏览器的同源安全策略默认阻止网页 跨域 获取资源, 但如果接口配置了CORS 相关的 HTTP 响应头, 就可以解除浏览器的跨域访问限制
5.4 CORS 的注意事项
- CORS 主要在服务器端 进行配置, 客户端浏览器无需做任何额外配置, 即可请求开启CORS接口
- CORS在浏览器中有兼容性, 只支持 XMLHttpRequest Level2 的浏览器
5.5 CORS 响应头部 - Access-Control-Allow- Origin
响应头部中可以携带一个 Access-Control-Allow-Origin 字段
Access-Control-Allow-Origin:| *
其中, origin参数的值指定了 允许访问该资源的外域URL
例如
res.setHeader('Access-Control-Allow-Origin', 'http://www.baidu.com')
如果指定了 Access-Control-Allow-Origin 字段值为 通配符 * , 表示允许任何域的请求
res.setHeader('Access-Control-Allow-Origin', 'http://www.baidu.com')
5.6 CORS响应头部 - Access-Control-Allow- Headers
默认情况下, CORS 仅支持 客户端向服务器发送如下9个请求头
- Accept
- Accept-Language
- Content-Language
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-Type (值仅限于text/plain , multipart/form-data , application/x-www-form-urlencoded 三者之一)
如果客户端向服务器发送了额外的请求体信息, 则需要在服务器端, 通过Access-Control-Allow- Headers 对额外的请求头进行声明
res.setHeader('Access-Control-Allow- Headers', 'Content-Type, X-Custom-Header')
5.7 CORS响应头部 -Access-Control-Allow- Methods
默认情况, CORS仅支持客户端发起 GET POST HEAD 请求
如果客户端希望通过 PUT DELETE 等方式请求, 则需要通过Access-Control-Allow- Methods 来指明实际请求所允许使用的 HTTP方法
res.setHeader('Access-Control-Allow- Methods' , 'POST, GET, DELETE, HEAD')
res.setHeader('Access-Control-Allow- Methods' , '*') //通配符, 允许所有请求方法
5.8 CORS 请求分类
客户端请求CORS接口时, 根据请求方式和请求头不同, 把CORS请求分为两大类
- 简单请求
- 预检请求
5.9 简单请求
同时满足 :
- 请求方式 : GET POST HEAD 三者之一
- HTTP头部信息不能超过 9 个字段
5.10 预检请求
简单请求的对立面
只要符合一下任意一个条件
- 请求方式为: GET POST HEAD 之外的类型
- 请求头中包含自定义请求头部字段
- 向服务器发送了 application/json 格式的数据
在浏览器与服务器正式通信之前,浏览器会先发送OPTION请求进行预检,以获知服务器是否允许该实际请求,所以这一次的OPTION请求称为 “预检请求〞。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据
5.11 简单请求和预检请求的区别
- 简单请求的特点:客户端与服务器之间只会发生一次请求。
- 预检请求的特点:客户端与服务器之间会发生两次请求,OPTION预检请求成功之后,才会发起真正的请求。
6 JSONP 接口 6.1 回顾 JSONP 概念与特点
概念:浏览器端通过 script 标签的src属性,请求服务器上的数据,同时,服务器返回一个函数的调用。这种请求数据的方式叫做JSONP。
特点 :
- JSONP不属于真正的Ajax请求,因为它没有使用XMLHttpRequest这个对象。
- JSONP仅支持GET请求,不支持POST、PUT、DELETE等请求。
6.2 创建JSONP 接口的注意事项
如果项目中已经配置了CORS跨域资源共享,为了防止冲突,必须在配置CORS中间件之前声明JSONP的接口。否则JSONP接口会被处理成开启了CORS的接口。示例代码如下:
//优先创建JSONP接口【这个接口不会被处理成CORS接口】
app.get('/api/jsonp',(req, res) => {})
//再配置CORS中间件【后续的所有接口,都会被处理成CORS接口】
app.use(cors())
//这是一个开启了CORS的接口
app.get('/api/get',(req, res) => {})
6.3 实现 JSONP 接口的步骤
- 获取客户端发送过来的回调函数的名字
- 得到要通过JSONP形式发送给客户端的数据
- 根据前两步得到的数据,拼接出一个函数调用的字符串
- 把上一步拼接得到的字符串,响应给客户端的<script>标签进行解析执行
app.get('/api/jsonp',(req, res) => {
//1.获取客户端发送过来的回调函数的名字
const funcName = req.query.callback
//2.得到要通过JSONP形式发送给客户端的数据
const data ={name:'zt',age:22}
//3.根据前两步得到的数据,拼接出一个函数调用的字符串
const scriptst r= `${funcName}(${JSON.stringify(data)})`
//4.把上一步拼接得到的字符串,响应给客户端的


