當前位置: 妍妍網 > 碼農

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多名前端小夥伴在等著一起學習哦 -->