基于koa2中间件原理实现拦截任意对象方法的调用

目的

本文目的在于总结前端开发过程中,对对象的函数进行拦截的通用性解决办法。

前言

在一个系统软件的开发过程中,无论是前后端开发,都经常会出现这么一种需求,就是对某一个方法进行拦截。在java中,有AOP面向切面的编程方式,可以很方便地对某一个对象或者对象的方法进行代理,在前端开发,JavaScript这一块,如果要对一个对象或者方法进行代理,可以简单地自己手动进行操作,无需其他依赖,下面以对对象的函数进行代理举例说明:

let util = {
    name: '线上',
    async placeOrders(param) {
        console.log(`1--下订单-->>${param}`)
        return Promise.resolve(`${this.name}下订单-->>${param}`)
    },
}

async function start() {
    function errorHandler(response) {
        console.error(`${response}:下单失败!!!`)
    }
    let resp1 = await util.placeOrders('汽车').catch(errorHandler)
    !!resp1 && console.log(`${resp1}:下单成功!!!`)
}

start()

结果:
这里写图片描述

可以看到这个util对象,有一个下单的函数,通过执行util对象的下单函数,执行下单业务逻辑。为什么这个placeOrders函数返回的是一个Promise对象,因为像这种下单的动作,往往需要请求后台服务器,这个过程是异步的,所以这里使用promise处理,结合es7的async/await语法,这里就是请求数据的比较简单的示例。现在有一个需求,就是在下单的时候,检查下单的用户是否有权限下单,现在我们对util的placeOrders函数进行简单代理:

let util = {
    name: '线上',
    async placeOrders(param) {
        console.log(`1--下订单-->>${param}`)
        return Promise.resolve(`${this.name}下订单-->>${param}`)
    },
}
let _func = util.placeOrders
util.placeOrders = async function (param) {
    console.log('2--start')
    let response = await _func.apply(this, arguments)
    console.log('3--end')
    return Promise.resolve(response)
}
async function start() {
    function errorHandler(response) {
        console.error(`${response}:下单失败!!!`)
    }
    let resp1 = await util.placeOrders('汽车').catch(errorHandler)
    !!resp1 && console.log(`${resp1}:下单成功!!!`)
}

start()

可以看到,就是比原来的多了这么一部分代码:

let _func = util.placeOrders
util.placeOrders = async function (param) {
    console.log('2--start')
    let response = await _func.apply(this, arguments)
    console.log('3--end')
    return Promise.resolve(response)
}

这一段代码,就是对util的placeOrders函数进行了代理,看看结果:

这里写图片描述

可以看到,我这里在下单前后,执行了自己的操作,简单输出了start和end,现在我们对下单操作进行限制,只能对拥有的产品进行下单:

let util = {
    name: '线上',
    async placeOrders(param) {
        console.log(`1--下订单-->>${param}`)
        return Promise.resolve(`${this.name}下订单-->>${param}`)
    },
}

let prods = [
    '汽车',
    '自行车',
    '货车'
]

let _func = util.placeOrders
util.placeOrders = async function (param) {
    console.log('2--start')
    let response
    if (prods.indexOf(param) > -1) {
        response = await _func.apply(this, arguments)
    }
    else {
        response = Promise.reject(param)
    }
    console.log('3--end')
    return Promise.resolve(response)
}

async function start() {
    function errorHandler(response) {
        console.error(`${response}:下单失败!!!`)
    }

    let resp1 = await util.placeOrders('汽车').catch(errorHandler)
    !!resp1 && console.log(`${resp1}:下单成功!!!`)
    let resp2 = await util.placeOrders('货车').catch(errorHandler)
    !!resp2 && console.log(`${resp2}:下单成功!!!`)
    let resp3 = await util.placeOrders('电视机').catch(errorHandler)
    !!resp3 && console.log(`${resp3}:下单成功!!!`)
}

start()

这里写图片描述

可以看到,我这里将所有可以使用的产品记录在prods数组中,在代理中对这个方法进行了拦截

这篇文章只是讲述了对对象的一个函数进行简单中间件拦截,更复杂的拦截,比如多层中间件拦截,路由匹配拦截等,请看我的博客:基于mpvue-router-patch实现路由拦截

猜你喜欢

转载自blog.csdn.net/mate_ge/article/details/81195527