在公共函数中区分上层调用者的模型

来源:互联网 发布:淘宝模特招聘要求 编辑:程序博客网 时间:2024/05/22 08:12

一、背景及问题详述:

  在编码时常常会将多次用到的公共函数封装之后,供其他函数调用。而在调用时,免不了需要根据上层调用函数的不同有不同的结果。
  举几个最近遇到的具体的场景:

1.UI界面的刷新按钮

  UI界面的刷新按钮,其功能定义不同于F5的刷新整个页面。而是通过给定的url再次获取页面中指定的表格数据、图片等。以表格为例,为方便用户操作和减轻前端压力,表格常常会有分页、搜索功能。当存在分页功能时,搜索就必须后台处理(除非你想实现这样的效果————只告诉用户当前页有几项匹配,即使在后台保存的数据中存在其他的匹配项,也忽略),此时每一次搜索、翻页都是通过url请求数据来实现的。那刷新按钮需要实现的功能就是,记录最近一次的请求,点击刷新时重新获取一次数据。
  按理说实现起来简单啊,用个变量保存最近使用的url就好了,刷新就取这个变量再请求一次。的确,如果自己从头写请求,写表格的展现方式,这不失为一种解决方式。但我想现在很少有人在工作中会从头写,都是使用第三方的js库。比如,笔者在项目中使用的就是基于SlickGrid(https://github.com/mleibman/SlickGrid)再次封装的框架,该框架不支持动态传入url,取代的是在创建时指定一个baseUrl,在load数据时调用此url,之后若需要实现过滤效果,则需传入一个filter对象(JSON形式),由其内部拼装成baseUrl?key=value&name=tom的形式,再调用此url,可气的是封装好的对象不返回当前使用的url。
   当时为了解决此问题,考虑过修改框架,增加一个方法,将当前使用的url暴露出来。当然这是最后的方法,因为太蠢太暴力。之后详细分析代码,发现两条流程有差异,也有联系。正常获取时,走load方法;过滤时需要先自行拼装json并传入对象,最后还是会调用load方法。
  最后采用设置一个变量flag并初始化为false,当走过滤时,将flag置为true,并保存filter对象,在load执行时的回调函数中,先根据flag的值判断是过滤流程还是直接获取,在处理完相应业务后,再将flag置false。
  整个流程中flag最终都会被置为false,唯一flag为true的时候就是经过过滤,业务处理完之前。
  之前的刷新实现就是根据flag值判断是过滤还是直接获取后,用同一个函数封装处理如过滤则

        func = function(){                    obj.setFilter(filter);                    obj.load();                }                func = function (){                    obj.load();                }

  最后点击刷新时直接调用函数func();

2.DOM元素事件委派

  同样是使用封装过的控件(公司内部使用,样式统一,因信息安全问题无法贴代码),因原生select丑爆了且不可编辑,在封装select控件时,隐藏了select,以input显示,同时在功能上即支持用户下拉选择(通过css样式和事件委派,使用隐藏的select实现),也可支持用户输入(input实现),即界面显示的是一个有着select功能和视觉效果的input框!
  感觉屌屌的,马上问题就来了——参数检查。禁用input的输入还好,选什么就显示什么,怎么检查都好。但同时支持选择和输入时,检查就有问题。监听select的select事件,此事件触发时只是选中了,但值还没有填到input中,只能通过检查select的值来检查。而input的input方法(为了能感知到用户用鼠标复制黏贴而监听的input事件)因为用户输入的,肯定是取input的值检查合理,input事件处理完后会再执行select的select事件(因为有一个小功能,根据输入的input值会匹配下拉框现有的值,类似于百度搜索输入)。此时select用自己的逻辑检测并覆盖之前input的结果。然后悲剧。
  最后同例一一样使用一个flag用以在公共的函数select中判断是哪个流程调用了该方法。区分执行各自的逻辑。

二、模型说明

  抽取公共部分分析:
这里写图片描述
  全局定义flag=false,在每次公共函数结束时将flag置为false,flag只有在经过特性函数,且未退出公共函数时才为true,以此判断这一次流程是否走过特性函数。流程可反复循环的调用。
  将flag换为整数,可以区分多个特性分支到底走了哪条。
  这里写图片描述

三、扩展和遗留问题

1.input的input事件

该事件在标准浏览器中良好支持,IE9以下不支持。需使用IE专用属性onpropertychangeoninput事件在value改变且失去焦点时实时触发,但是通过js改变value时不会触发;onpropertychange事件是任何属性改变都会触发,每增加或删除一个字符就会触发,通过js改变也会触发该事件

2.keyup事件

keyup事件未参数检测常用的事件。但经测试,该事件在select之前和之后各触发一次。不适用该模型

3.相似模型讨论

先调用公共函数,在调用下层函数(也可能没有下层函数)。
目前有两条思路:
  公共函数处理一遍,若有下层函数,推翻公共函数的结论,以下层函数结果为准(无脑覆盖流)。缺陷,过渡过程有时让人难以接受。还是以参数检测为例,先显示错误提示,再检测一次,发现合法,再隐藏,表现就是用户输入一个字符,错误提示闪一下又没了,坑。
  为了解决上面的问题。考虑过再公共函数中使用一个定时器,我得到结果,但我傲娇,我要等一段时间(比如20ms)在将结果反馈展现。如果后续的下层调用者赞同我,以我的结果为准,定时器超时后显示结果,如果下层调用者结果与我不同,取消定时器,由下层调用者显示结果。(公共函数:意见一致时,我说了算,不一致时,别人说了算~)。
  

4.缺陷与待思考、优化点

只适用于单线程,目前在前端使用足够。但该模型在多线程时需注意同步互斥,具体可参考操作系统关于信号量的表述。公共函数本身的立意是处理相同的逻辑,现在需在其中根据特性实现不同的功能,实际以违背了最初的用意,若代码全为自己实现,应考虑将对特性的区分处理抽取出来,独立处理。
0 0
原创粉丝点击