目的
本文目的在于总结前端开发过程中,对对象的函数进行拦截的通用性解决办法。
前言
在一个系统软件的开发过程中,无论是前后端开发,都经常会出现这么一种需求,就是对某一个方法进行拦截。在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实现路由拦截