大杂烩,记录贴。包含一个简版koa框架的核心实现

前置知识:关于async和await的理解

https://segmentfault.com/a/1190000007535316

  • await必须包裹在async函数里
  • async函数执行返回的是一个promise对象
  • await在等什么?等一个promise,获取他的resolve的值
  • 如果await后面的promise返回的是reject的值,那么需要使用try,catch进行包裹

koa2原理(use和next)

源码解读:https://zhuanlan.zhihu.com/p/34797505

自己实现一个简版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const http = require('http')

// 组合中间件
function compose(middlewareList) {
return function (ctx) {
//dispatch函数用于执行一个中间件
function dispatch(i) {
const fn = middlewareList[i]
try {
return Promise.resolve(

//这里fn的第二个参数就相当于next
fn(ctx, dispatch.bind(null, i + 1)) // promise
)
} catch (err) {
return Promise.reject(err)
}
}
return dispatch(0)
}
}

class LikeKoa2 {
constructor() {
this.middlewareList = []
}

use(fn) {
this.middlewareList.push(fn)
return this
}

createContext(req, res) {
const ctx = {
req,
res
}
ctx.query = req.query
return ctx
}

handleRequest(ctx, fn) {
return fn(ctx)
}

callback() {
const fn = compose(this.middlewareList)

return (req, res) => {
const ctx = this.createContext(req, res)
return this.handleRequest(ctx, fn)
}
}

listen(...args) {
const server = http.createServer(this.callback())
server.listen(...args)
}
}

module.exports = LikeKoa2

koa2的ctx对象

koa2的ctx封装了req和res,可以通过ctx直接取得,也可以通过ctx.request.xx的形式取得
常用的:

  • ctx.params
  • ctx.request.query
  • ctx.request.header
  • ctx.request.body( 需要使用body-parser插件)

利用cookie和session进行鉴权

作为一个网站有些资源需要登陆才能访问,有些不登陆也可以浏览。
如何实现鉴权?常用的方法是cookie和session

这里假设session存储在服务端内存中,是一个数组SESSION[ ]

  1. 用户访问某个url时,进行用户鉴权,有无cookie
  2. 没有cookie,响应设置cookie,比如userid: xxx01,在服务端SESSION[ ]中添加一个session{xxx01:{ }}
  3. 用户登陆,往SESSION中对应的session对象中写字段,比如username: xxx。此时SESSON数组中有一个session应该是这样的:ssession{xxx01:{username: xxx}}
  4. 请求时携带cookie,服务端获取userid去SESSION中进行查询,看username是否有值,判断是否登陆了

注意事项:

  1. 设置 cookie时应当设置过期时间
  2. session存储在服务器中重启就没了,需要进行持久化。可以考虑存在redis中或者直接加密后返回到cookie也可以

koa2常用插件

登陆鉴权相关

  1. koa-session(把session加密后存在cookie中,支持外部数据库)
    源码解读文章:https://segmentfault.com/a/1190000012412299

  2. koa-generic-session,koa-redis(这两个配套可以存储session到redis)

  3. Sequelize,操作mysql数据库(如果链接mysql需要安装mysql2驱动)

异常处理

js中try catch只能捕捉同步错误

异步代码的错误很难,通过使用promise和async和await可以简化异步的错误处理,使用try和catch
下面这样也是没用的,必须返回异步函数的promise包装

这样才对

AOP思想

自定义全局异常处理函数,最先注册,try next()即可,相当于调用链条

封装错误对象

状态码
error code
error message
request url

开发环境和生产环境的异常配置

开发环境下全局的非httpError捕捉需要再抛出去,方便开发时候调试
生产环境就不要抛了

一个作业题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class A {
constructor() {
this.nameA = 'a'
this.nameD = 'd'
}
validateA() {
console.log("A")
}
}

class B extends A {
constructor() {
super()
this.nameB = 'b'
}

validateB() {
console.log("B")
}
}

var b = new B()
// 编写一个函数findMembers,获取b的所有带前缀的属性和方法
const members = findMembers2(b, 'name', 'validate')