美文网首页
koa-router笔记

koa-router笔记

作者: 我叫Aliya但是被占用了 | 来源:发表于2019-07-16 23:12 被阅读0次

    基于koa,有自己的next(洋葱模型),有点像发布订阅

    用法(npmjs官网

    const Koa = require('koa')
    const Router = require('koa-router')
    const app = new Koa()
    const router = new Router()
    
    router.get('/', (ctx, next) => {
      console.log(222)
      ctx.body = 'ok'
      setTimeout(()=> next(), 2000)
    })
    router.get('/', (ctx, next) => {
      console.log(333)
      setTimeout(()=> next(), 1000)
    })
    router.get('/login', (ctx, next) => {
      ctx.body = 'ok'
      next()
    })
    router.get('/user/:id', (ctx, next) => {
      console.log(ctx.params, ctx.query)
      ctx.body = 'ok'
      next()
    })
    app.use(router.routes()).use(router.allowedMethods())
    app.use(async (ctx, next) => {
      console.log('access by ', ctx.url)
    })
    
    app.listen('3000')
    

    实现

    /** my router */
    class Layer {
        constructor (method, path, fn) {
            this.regexp = new RegExp('^' + path.replace(/:([^/]+)/g, '([^/?#]+)') + '$')
            this.params_keys = path.match(/:([^/]+)/g)
    
            this.method = method;
            this.path = path
            this.fn = fn
        }
        
        match (method, path) {
            let vals = path.match(this.regexp)
            if (this.method == method && vals) {
                // 处理params参数
                let params = {}
                this.params_keys && this.params_keys.forEach((item, index) => {
                    params[item.substr(1)] = vals[index+1]
                });
                return { is_match: true, params }
            }
            return { is_match: false }
        }
    }
    class Router {
        constructor () {
            this.middlewares = []
        }
    
        get (path, fn) {
            this.middlewares.push(new Layer('GET', path, fn))
        }
    
        post (path, fn) {
            this.middlewares.push(new Layer('POST', path, fn))
        }
    
        routes () {
            return (ctx, next) => {
                let match_router = this.middlewares.filter(middle => {
                    let result = middle.match(ctx.method, ctx.url)
                    if (result.is_match) {
                        ctx.params = result.params
                    }
                    return result.is_match
                })
                // 以中间件方式执行路由方法
                match_router.reduceRight((prev, next) => {
                    return async () => {
                        if (prev.is_called == 'yes') { 
                            throw new Error('next 只能调用一次')
                        }
                        prev.is_called = 'yes'
                        return await next.fn(ctx, prev)
                    }
                }, next)()
            }
        }
    
        allowedMethods () {
            return (ctx, next) => {
                next()
            }
        }
    }
    module.exports = Router
    

    二级路由

    // sub.js
    let Router = require('../koa-router')
    let router = new Router()
    
    router.prefix('/sub')
    router.get('/prat1', async (ctx, next) => {
        ctx.body = 'wrong! guess again'
        await next()
    })
    
    module.exports = router
    
    // app.js
    ……
    let sub_route = require('./routes/sub')
    ……
    app.use(sub_route.routes(), sub_route.allowedMethods())
    ……
    

    实现

    /** my router */
    class Layer {
        constructor (method, path, fn) {
            this.regexp = new RegExp('^' + path.replace(/:([^/]+)/g, '([^/?#]+)') + '$')
            this.params_keys = path.match(/:([^/]+)/g)
    
            this.method = method;
            this.path = path
            this.fn = fn
        }
        
        match (method, path, root) {
            if (root && path.startsWith(root)) {
                path = path.substr(root.length)
            }
            let vals = path.match(this.regexp)
            if (this.method == method && vals) {
                // 处理params参数
                let params = {}
                this.params_keys && this.params_keys.forEach((item, index) => {
                    params[item.substr(1)] = vals[index+1]
                });
                return { is_match: true, params }
            }
            return { is_match: false }
        }
    }
    class Router {
        constructor () {
            this.middlewares = []
            this.root = null
        }
    
        prefix (root) {
            this.root = root
        }
    
        get (path, fn) {
            this.middlewares.push(new Layer('GET', path, fn))
        }
    
        post (path, fn) {
            this.middlewares.push(new Layer('POST', path, fn))
        }
    
        routes () {
            return (ctx, next) => {
                let match_router = this.middlewares.filter(middle => {
                    let result = middle.match(ctx.method, ctx.url, this.root)
                    if (result.is_match) {
                        ctx.params = result.params
                    }
                    return result.is_match
                })
                // 以中间件方式执行路由方法
                match_router.reduceRight((prev, next) => {
                    return async () => {
                        if (prev.is_called == 'yes') { 
                            throw new Error('next 只能调用一次')
                        }
                        prev.is_called = 'yes'
                        return await next.fn(ctx, prev)
                    }
                }, next)()
            }
        }
    
        allowedMethods () {
            return (ctx, next) => {
                next()
            }
        }
    }
    module.exports = Router
    

    相关文章

      网友评论

          本文标题:koa-router笔记

          本文链接:https://www.haomeiwen.com/subject/onoxlctx.html