感受面向切面编程
什么是面向切面
初听面向切面编程时, 一头雾水, 什么是面向切面, 只听说过面向对象(OOP), 面向过程(PO), 函数式编程(FP), 面向切面 ? 面向的难道是某一个面?
面向搜索引擎后才了解到, 面向切面是一种编程范式(Aspect Oriented Programming), 简写 AOP, 特点是与原有逻辑解耦, 无侵入.
在后端开发工作中, 常见使用的场景是 断点调试/打印日志/…,
而在前端开发工作中, 应用场景比较灵活多变, 可以是在一次表单提交中, 在表单提交前作表单验证(前置), 或在表单提交后作数据刷新/页面跳转/Cookie 刷新等 (后置), 也可以在提交的同时作数据埋点(横向), 或是打印日志。。。
对于外部的新加入的逻辑, 为了不破坏原有的业务逻辑, 我们就可以使用 AOP 去组织代码, 分离 [业务逻辑] 与 [琐碎事务]
AOP 的关键概念点
- 前置(before) 在目标方法执行前执行
- 后置(after) 在目标方法执行后执行
- 异常(after throwing)在目标方法抛出异常时执行
- 环绕 (around) 在目标方法执行前后
前置执行函数
const before = function(fn, action) { return function(...args) { action.apply(this, args); const res = fn.apply(this, args); return { res, params: args }; }; };
后置执行函数
const after = function(fn, action) { return function(...args) { let res = fn.apply(this, args); action.apply(this, args); return { res, params: args }; }; };
异常执行函数
const throwing = function(fn, action) { let ret = { res: undefined, params: undefined }; return function(...args) { try { const res = fn.apply(this, args); return (ret = { res, params: args }); } catch (err) { action.apply(this, args); return (ret = { res: err, params: args }); } }; };
环绕执行函数
const round = function(fn, actionBefore, actionAfter) { return function(...args) { actionBefore.apply(this, args); const res = fn.apply(this, args); actionAfter.apply(this, args); return { res, params: args }; }; };
使用场景 — 请求记录
const request = config => axios.request(config); const ButtonClickFn = function () { ...do something } document.querySelector('#submit').click = before(ButtonClickFn, () => { request({ url: 'http://your_upload_log_url', method: 'GET', params: { TYPE: 'BUTTON_CLICK', POSITION: '' } }); });
使用场景 — 异常处理
const originRequest = config => axios.request(config); const wrapperedRequest = throwing(originRequest, function() { ...异常上报 });
其它实现方式
实际上除了使用高阶函数的方法实现, 我们还可以使用 ES7 的装饰器/Ojbect.defineProperty 实现, 或基于原型链去实现
原文地址:https://segmentfault.com/a/1190000021653151