前言:
为什么要写这篇文章,因为目前在做一个模块,其中没有涉及金钱的交♂易,但是牵扯到了一个很耗费时间的任务,暂且称之为“锻造任务”,锻造任务可以在用户对数据进行多次修改后执行,也可以伴随着每次修改同步执行。如果用户每次都去点击保存按钮,就要不断地去增加一个锻造任务,导致系统任务短时间激增造成资源浪费做大量无用功。
由于锻造任务是必须要执行的,用户多次点击会出现如下两种场景
- 好玩,用户页面维护好数据后,不断地点保存保存保存,后台增加了许多锻造任务。
- 临时起意,用户维护好页面后点击保存,但是这个用户跟搞需求的一样善变,在执行锻造任务的时候又做了多次修改,多次保存。
正文:
于是深思熟虑了一下可行的解决方案,并决定最终选择一个最佳方案,先说下可行方案:
1、前端页面增加按钮置灰或者页面遮罩:这种方法优点是页面直接阻断了用户进行多次点击的操作,实现起来也很简单
按钮变灰不可用方法:document.getElementById("crop").setAttribute("disabled", true);
按钮可用方法:document.getElementById("crop").removeAttribute("disabled");
问题是:当锻造任务执行时间较久会造成页面长时间等待状态,影响用户体验,于是放弃。
2、着手后台,针对前言说明的问题,建立一个请求队列,承接多次点击带来的多次请求。
- 一个session对应一个队列
- 第一次请求 到来时即刻执行,之后到来的请求被阻塞,并且当第一次请求执行完毕是,直接执行队列最后一条请求,用以更新用户在等待锻造任务是做出的额外修改,期间的请求统统放弃执行。
- 修改数据应该是原子性的,并且必须要最后一条修改数据的请求真正入库后在执行最后一条锻造任务
3、选择实现
使用队列来承接每一次请求,请求发送来则加入队列,然后锻造任务消费第一个请求,之后点击的请求都排队等待,当第一个任务执行完毕,自动屏蔽掉中间的任务,取最后的那一项。