当前位置: 欣欣网 > 码农

20行代码实现【洋葱模型】,其实没那么难理解~

2024-05-14码农

每日知识分享~

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心~

洋葱模型

洋葱模型是什么呢?作用是什么呢?

先说说他的作用吧,他的作用是为了对一个请求的整个生命周期做一个统一的管理,一个请求的生命周期包括请求、响应。由于实现方式像一层一层剥开洋葱,所以叫洋葱模型~

举例子

可能很多人会觉得一脸懵逼?不知道我在表述什么?那我通过两个例子来说明,大家可能就比较清晰了~

Axios 拦截器

相信很多人在项目中都用过 Axios 的拦截器

  • 请求拦截器

  • 响应拦截器

  • axiosInstance
    .interceptors
    .request.use((config) => {
    console.log(config) // {}
    config.name = 'sunshine_lin'
    }
    axiosInstance
    .interceptors
    .response.use((res) => {
    console.log(res.config)
    // { name: 'sunshine_lin' }
    }

    在每次请求中,请求拦截器和响应拦截器中,获取到的config是相通的,也就是同一个对象。

    我们甚至可以多个拦截器

    // 请求拦截器1
    axiosInstance
    .interceptors
    .request.use((config) => {
    console.log(config) // {}
    config.name = 'sunshine_lin'
    return config
    }
    // 请求拦截器2
    axiosInstance
    .interceptors
    .request.use((config) => {
    console.log(config)
    // { name: 'sunshine_lin' }
    config.age = 20
    return config
    }
    // 响应拦截器1
    axiosInstance
    .interceptors
    .response.use((res) => {
    console.log(res.config)
    // { name: 'sunshine_lin',
    // age: 20
    // }
    res.data = 1
    return res
    }
    // 响应拦截器2
    axiosInstance
    .interceptors
    .response.use((res) => {
    console.log(res.data) // 1
    return res
    }





    其实基础比较好的同学,可以想象出他的实现原理基本(伪代码)就是:

    // 伪代码
    // 收集
    const tasks = []
    const use = (fn) => {
    tasks.push(fn)
    }
    // 执行
    const config = {}
    tasks.forEach(fn => {
    config = fn(config)
    })

    Koa

    Koa 是一个 Nodejs 的框架,他也有洋葱模型的实践,比如:

    const koa = new Koa()
    koa.use(async (ctx, next) => {
    console.log(1)
    console.log(ctx) // {}
    await next()
    console.log(ctx) 
    // { name: 'sunshine_lin', age: '20' }
    console.log(2)
    })
    koa.use(async (ctx, next) => {
    console.log(3)
    ctx.name = 'sunshine_lin'
    await next()
    console.log(4)
    })
    koa.use(async (ctx, next) => {
    console.log(5)
    ctx.age = '20'
    })
    koa.listen(3000)


    执行的结果为:

    就感觉是,遇到 next 就一层一层往两边掰开。

    简单实现洋葱模型

    functionaction(instance, ctx{
    // 记录索引
    let index = 1
    functionnext() {
    // 记录执行的中间件函数
    const nextMiddleware = instance.middlewares[index]
    if (nextMiddleware) {
    index++
    nextMiddleware(ctx, next)
    }
    }
    // 从第一个开始执行
    instance.middlewares[0](ctx, next)
    }

    classKoa{
    middlewares = []
    use(fn) {
    this.middlewares.push(fn)
    }
    listen(port) {
    Promise.resolve({}).then((ctx) => {
    action(this, ctx)
    })
    }
    }

    结语

    我是林三心

  • 一个待过 小型toG型外包公司、大型外包公司、小公司、潜力型创业公司、大公司 的作死型前端选手;

  • 一个偏前端的全干工程师;

  • 一个不正经的掘金作者;

  • 逗比的B站up主;

  • 不帅的小红书博主;

  • 喜欢打铁的篮球菜鸟;

  • 喜欢历史的乏味少年;

  • 喜欢rap的五音不全弱鸡

  • 如果你想一起学习前端,一起摸鱼,一起研究简历优化,一起研究面试进步,一起交流历史音乐篮球rap,可以来俺的摸鱼学习群哈哈,点这个,有7000多名前端小伙伴在等着一起学习哦 -->