乐趣区

关于javascript:nodejs-路由中间件mysql

这几天天天搞到这么晚,我看明天的内容看起不多啊,不晓得为什么学着学着就到了这么晚。明天的内容还是有点多哈,有点自我矛盾了,再次一一道来。

1.

首先明天先看到路由的概念,什么叫做路由?

路由就是映射关系,在 express 中路由指的是客户端申请和服务器处理函数的映射关系,路由有三局部组成:申请类型、申请 url 和处理函数。

app.get(url,callback) 其实就跟咱们后面所说的监听事件一样一一样的。

const express = require('express')
const app = express()
app.get('/', (req, res) => {res.send('收到 get 申请')
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))  

这就是一个最简略的路由。路由的匹配过程,每当一个申请达到服务器器后,须要先通过路由匹配,当申请类型和 url 匹配胜利后才会调用前面的申请函数。、

用法

最简略的用法就是像咱们下面那样间接挂在实例上,这也是不举荐的,因为一个申请就要挂一个很麻烦很繁琐。

迷信的办法应该是创立路由模块。

分为五个步骤:

别离是创立路由 js 文件、调用 express.Router 创立路由对象、挂载路由、向外导出路有对象最初咱们的入口文件须要导入,在通过 app.use 去注册

// 1. 导入 express
const express = require('express')
// 2. 创立路由对象
const router = express.Router()
// 3. 挂载路由
// 3.1 挂载路由获取用户的信息
router.get('/user/:id', (req,  res) => {res.send(req.params)
})
// 3.2 挂载路由承受用户发送的申请
router.post('/post', (req, res) => {res.send('post 胜利')
})
// 4. 向外共享路由成员
module.exports = {
    express,
    router 
}
const express = require('./02 模块化路由')
const app = express.express()
//  注册路由
app.use(express.router)
app.listen(80, () => console.log('express server running at http://127.0.0.1'))

这里说一下 app.use 昨天也看到了,他其实就是一个用来注册全局中间件的。而后咱们还能够为路由挂载前缀,也是通过 app.use 来增加办法同昨天根本一样

2.

中间件

指的是业务流程的两头解决环节。

就是当客户申请达到服务器后,可间断调用多个中间件对这个申请进行预处理,最初通过路由发送进去。

中间件的实质是一个函数根路有相似然而多了一个参数,next 参数。

next 是一个函数它的作用就是实现多个中间件间断调用的要害,把流转关系转给下一个中间件或者路由,每个中间件都有一个 next 一个转下去转到路由没有了就响应给客户端了。

2.1

咱们先看到全局失效的中间件,意思就是客户发动的任何申请,他都会触发,间接通过 app.use 来注册即可

const express = require('express')
const app = express()
// 中间件
const mw = function(req, res, next) {// res.send('这是中间件环节')
    console.log('这是中慢慢环节')
    next()}
// 通过 app。use 定义为全局失效的中间件
app.use(mw)

app.get('/user', (req, res) => {res.send('这是 get 申请')
})

app.post('/post', (res, req) => {res.send('这是一个 post 申请')
})
app.listen(80, () => {console.log('http://127.0.0.1');
})

中间件的作用:

多个中间件共享同一个 res 和 req,所以能够在上游的中间件定义好这些对象,上游间接用包含路由也能够用

怎么来定义多个全局中间件,间接通过 app.use 定义多个即可就像昨天所说的托管动态资源,有多个目录就注册多个

2.2

部分中间件

不是用 app.use 只对局部的路由无效,路由 的参数规定 也产生了扭转

const express = require('express')
const app = express()

const mw = function(req, res, next) {req.time = Date.now()
    next()}

app.get('/', mw, (req, res) => {res.send('部分失效' + req.time)
})
app.get('/user', (req, res) => res.send('没有失效') + req.time)
app.listen(80, ()=> {console.log('http://127.0.0.1');
})

定义多个部分中间件

写多个函数过后在参数这里能够用逗号隔开,也能够间接写一个数组

有一个注意事项:就是肯定要在路由之前去注册中间件,不然路由执行完了谁还来执行中间件。

2.3

中间件的分类

①利用级别中间件

就是通过 get、post、use 绑定到 app 上的中间件

②路由级别中间件

就是在咱们方才的路由模块外面来交叉的一个中间件

③谬误级别中间件

这个有点说法

它是专门用来捕捉错误信息的而且形参变为了四个

他也是惟一一个卸载路由前面的中间件

const express = require('express')
const {rename} = require('fs')
const app = express()
app.get('/', (req, res) => {
    // 1. 人为抛出一个谬误,一旦有错前面的响应就不会执行了
    throw new Error('服务器外部产生谬误')
    res.send('我不能执行进去')
})

// 2. 谬误中间件
app.use((err,req,res,next) => {
    // 2.1 向服务器打印谬误
    console.log(err.message);
    // 2.2 向客户端发送谬误
    res.send(err.message)
    // 这样做 益处就是,后面如果产生了谬误导致了整个服务器曾经解体了,什么都执行不了了,这样一来,就能够失常输入错误信息,失常执行前面代码
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))

④内置中间件

三个内置的中间件别离是 express.static 这个曾经说过了后面

express.json 这是拿来解析 json 格局数据的

express.urlencoded 这是拿来解析 urlencoded 格局数据的

前面两个个别会配合 req.body 来拿申请体数据再给他们拿来解析了

const express = require('express')
const app = express()
// 留神这是中间件 所以必须配置到路由之前
app.use(express.json())
app.use(express.urlencoded({extended : false}))
app.post('/', (req, res) => {
    // 通过 req.body 能够拿到申请体数据
    // postman 在测试的时候抉择 body 外面的 raw 再把 text 抉择 json 就能够发送 json 数据了
    console.log(req.body);
    // 没有解析之前对于 json 数据是 undefined
})

// 测试 urlencoded 数据体
// 这个数据体的格局是 x -www-form-urlencoded
// 固定写法
app.post('/user', (req, res) => {
    // 没解析前时空对象
    console.log(req.body);
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))

⑤第三方中间件 间接 npm 装置导入通过 app.use 注册即可应用

2.4

自定义中间件

这里做一个案例自定义一个相似于 express.urlencoded 性能的中间件能够解析申请体数据

const express = require('express')
const app = express()
// 4. 利用 node 外面的一个内置模块解析申请体数据,在 node 外面内置了一个 querystring 模块是专门用来解决查问字符串的,这个模块提供的
// parse()函数能够把查问字符串转换为对象
const qs = require('querystring')

// 1. 定义中间件
app.use((req, res, next) => {
// 2. 监听 data 事件,因为既然是服务器,那么必定会接管到癞子客户端的申请,如果有时候申请量过大,就会分批次传给服务器数据,所以 data 事件可能触发屡次
// 就须要把每一次的数据最初拼接起来
let str = ''req.on('data', chunk => {str += chunk})
// 3.req 的 end 事件当申请体接管结束会主动登程 end 事件能够在这里解决残缺的申请体数据
req.on('end', () => {console.log(str);
    str = qs.parse(str)
    console.log(str);
    // 5. 解说洗出来的对象给到 req.body
    req.body = str
    next()})
})




app.post('/', (req, res) => {res.send(req.body)
})
app.listen(80, () => console.log('http://127.0.0.1'))

而后将自定义中间件进行了一个模块化

// 4. 利用 node 外面的一个内置模块解析申请体数据,在 node 外面内置了一个 querystring 模块是专门用来解决查问字符串的,这个模块提供的
// parse()函数能够把查问字符串转换为对象
const qs = require('querystring')
// 因为他人导入进来是间接注册应用所以能够把 app 开服务器等一些多余的代码省略就保留 app.use 外面的
const bodyParse = (req, res, next) => {
    // 2. 监听 data 事件,因为既然是服务器,那么必定会接管到癞子客户端的申请,如果有时候申请量过大,就会分批次传给服务器数据,所以 data 事件可能触发屡次
    // 就须要把每一次的数据最初拼接起来
    let str = ''req.on('data', chunk => {str += chunk})
    // 3.req 的 end 事件当申请体接管结束会主动登程 end 事件能够在这里解决残缺的申请体数据
    req.on('end', () => {console.log(str);
        str = qs.parse(str)
        console.log(str);
        // 5. 解说洗出来的对象给到 req.body
        req.body = str
        next()})
}

module.exports = bodyParse 
const bodyParse = require('./ 自定义中间件模块化')
const express = require('express')
const app = express()
app.use(bodyParse)
app.post('/', (req, res) => {// res.send('收到 get 申请')
    console.log(req.body);
})
app.listen(80, () => console.log('express server running at http://127.0.0.1'))  

3.

咱们持续看到用 express 来写接口

分为了三个步骤

创立根本服务器、创立 api 路由模块、编写 get 接口

这是路由模块

// 2. 写 api 路由模块 就是将路由模块化 因为那边引入进来须要用 use 来注册同时挂载 api 前缀
const  express = require('express')
const router = express.Router()


// 3. 编写 get 接口
router.get('/get', (req, res) => {
    // 3.1 首先拿到用户传过来的数据
    let data = req.query
    // 3.2 把数据发送给客户端
    res.send({
        status : 0, // 0 示意胜利 1 示意失败
        msg : 'get 申请胜利',
        data : data // 把数据返回给客户端
    })
})

// 4. 编写 post 接口
router.post('/post', (req, res) => {
    // 4.1 客户端发过来的数据
    let data = req.body
    res.send({
        status : 0,
        msg :  'post 申请胜利',
        data : data
    })
})

module.exports = router

其实次要就是通过 req 的那几个属性拿到数据后,再通过 send 办法发给客户端,上面是入口文件次要就是开启服务器,而后解析下数据

// 1. 创立根本 web 服务器
const express = require('express')
const app = express()


// 2.1 导入路由模块 并挂载前缀
const router = require('./router')
// 4.2 注册内置中间件 不然 req.body 解析不进去 
app.use(express.urlencoded({extended : false}))
// 5.cors 解决跨域
const cors = require('cors')
app.use(cors())
app.use('/api', router)
app.listen(80, ()=> {console.log('http://127.0.0.1');
})

有些货色要把前面看了才晓得哈我只是先拿上来了。

4.

cors 和 jsonp

咱们方才这个案例其实是有 bug 的,就是有跨域的问题,咱们创立一个 html 文件通过 button 来获取数据这个时候就会因为协定不同而被同源策略组织。

咱们后面也说过解决跨域一个是 cors 一个是 jsonp,这里必定不能用 jsonp 因为他只反对 get,那么怎么来用 cors 呢?

间接三部曲装置导入加注册就解决了跨域问题了,就这么简略。

4.1

什么是 cors

就是由一系列 http 响应头组成,同源策略碰到这个头就会解除限制。

cors 个别是在服务器进行配置,客户端不须要。

上面是一些理解性内容

响应头部:

第一个 res.setHeader(‘Access-Control-Allow-Orign’,‘http:wwwssss。聪慧、’)

这是示意只容许前面这个网站的域来拜访,如果为 * 那就示意容许任何域来拜访了

第二个是后面的根底上为 Allow-Headers

咱们的 cors 默认值只有 9 个申请头如果超出了这个九个头就必然失败申请,在这个九个之外的能够通过这个代码来增加上来

第三个后面的根底上 -Methods

cors 默认只反对 get post head 除此之外的须要用这个来设置。

4.2

当初不是理解内容了。

cors 申请分类

大体上分为简略申请和预检申请。

什么叫做简略申请

满足两个条件:

一个是申请形式在默认的三个之内,一个是 http 申请头不能超过默认的九个

什么是预检申请

三个条件达到其中一种都是

一个是申请头在九个之外,一个是申请形式在三个之外,还有一个就是发送过去的数据是 json 数据

那么他们的区别是什么呢

很简略,简略申请只会发送一次申请,而预检申请会发送两次申请,为什么?

因为预检申请会在服务器与客户端正是连贯之前,提前发一个 option 的申请作为预检,看服务器是否跟这个格局的申请相连接,只有申请胜利了才会开始正式申请,携带实在数据。

5.

明天最初一个内容 jsonp 接口

首先要留神一下,如果说曾经配置了 cors 那么必须在配置 cors 之前去申明 jsonp 接口,不然会错乱的。

做这个接口之前咱们先来回应一下 jsonp 的一个常识,首先它是来解决跨域的,咱们通过 script 标签把函数传进来再去调用接口这种形式就叫 jsonp

// 1. 创立根本 web 服务器
const express = require('express')
const app = express()


// 2.1 导入路由模块 并挂载前缀
const router = require('./router')
// 4.2 注册内置中间件 不然 req.body 解析不进去 
app.use(express.urlencoded({extended : false}))
// 6.jsonp 接口必须写在 coes 之前
app.get('/api/jsonp', (req, res) => {
    // 6.1 获取回调函数的名字
    let fn = req.query.callback
    // 6.2 定义你要发送回去的数据对象
    let data = {name : '张三', age : 15}
    // 6.3 模仿函数调用
    let fnDiao = `${fn}(${JSON.stringify(data)})`
    // 6.4 数据返回回去
    res.send(fnDiao)
})
// 5.cors 解决跨域
const cors = require('cors')
const {json} = require('body-parser')
app.use(cors())
app.use('/api', router)
app.listen(80, ()=> {console.log('http://127.0.0.1');
})

退出移动版