乐观锁机制解决多层嵌套异步ajax问题
前言
在项目中我们通常需要使用ajax异步嵌套去请求数据并做数据的展示,当我们多次快速的多次的发起ajax,因为ajax是异步的,每个ajax触发回调的时间都是不可控的,这样就会造成前面发起的ajax跟后面发起的ajax都有可能去修改同一个DOM,导致展示的数据顺序错乱或数据重复,我们希望DOM展示的最新的数据,也就是最后一个ajax的回调去操作DOM就足够了。这里我使用类似Hibernate的乐观锁机制,全局版本号versions初始为0,versions++(当前ajax的版本号),同时versions传到getRacksByRoomIdAndAppend,并且会跟随request、response传入到嵌套的ajax,同时在两层ajax的回调函数版本号校验,当ajax版本号与全局版本号不相等时(另一个时间点再次触发flush)说明有新的flush被触发,停止当前ajax。
Hibernate的乐观锁机制:乐观锁不是真的去加锁,是一种冲突检测机制。常用的是版本的方式是:每个表中都有一个版本字段version,当用户更新数据库后,版本号+1,另一个用户修改后再+1,当用户发起更新发现数据库当前版本号与读取数据时版本号不一致(等于或小于数据库版本号)则说明在你上次读取数据后有人对数据进行了更新,这时候你的数据就是脏数据。
代码编写
本例中,机房里面有机架,机架里面有设备(room-->rack-->equipement)
html:
<button class="btn btn-default" onclick="flush()">刷新</button>
<div id="text-div"> </div>
js:
//全局版本号
var versions = 0; //刷新
function flush() {
versions++;
console.log("flush(),versions=" + versions);
getRacksByRoomIdAndAppend(111, versions);
} //根据机房id获取所属机架集合
function getRacksByRoomIdAndAppend(roomId, ajaxVrsions) {
$.post(ctx + "/text1", {versions: ajaxVrsions, roomId: roomId}, function (result) {
result = JSON.parse(result.data);
// result.racks 是请求回来的机架数据集合
// result.versions 是当前ajax的版本号
// versions 是全局版本号
for (var i = 0; i < result.racks.length; i++) {
//检查版本号
if (result.versions === versions) {
//第一次之前empty
if (i === 0) {
$("#text-div").empty();
console.log("最新的ajax开始执行回调,versions=" + result.versions);
}
var rack = result.racks[i];
$("#text-div").append("<p id='" + rack.id + "'>" + rack.name + "</p>");
getEquipmentByRackIdAndAppend(rack.id, result.versions);
} else {
break;
}
}
});
} //根据机架id获取所属设备集合
function getEquipmentByRackIdAndAppend(rackId, ajaxVrsions) {
$.post(ctx + "/text2", {versions: ajaxVrsions, rackId: rackId}, function (result) {
result = JSON.parse(result.data);
for (var i = 0; i < result.equipments.length; i++) {
//检查版本号
if (result.versions === versions) {
var equipment = result.equipments[i];
$("#" + equipment.parentId).append(" <p>" + equipment.name + "</p>");
} else {
break;
}
}
});
}
java:
@PostMapping("text1")
public ResultModel<String> text1(String versions, String roomId) throws InterruptedException {
Thread.sleep(3000);//模拟网络阻塞
String racks = "{\"versions\":" + versions + ",\"racks\":[{\"id\":1,\"parentId\":111,\"name\":\"rack1\"},{\"id\":2,\"parentId\":111,\"name\":\"rack2\"}]}";
return ResultModel.of(racks);
}
@PostMapping("text2")
public ResultModel<String> text2(String versions, String rackId) throws InterruptedException {
Thread.sleep(3000);//模拟网络阻塞
String equipments = null;
if ("1".equals(rackId)) {
equipments = "{\"versions\":" + versions + ",\"equipments\":[{\"id\":11,\"parentId\":1,\"name\":\"equipment11\"},{\"id\":12,\"parentId\":1,\"name\":\"equipment12\"}]}";
}
if ("2".equals(rackId)) {
equipments = "{\"versions\":" + versions + ",\"equipments\":[{\"id\":21,\"parentId\":2,\"name\":\"equipment21\"},{\"id\":22,\"parentId\":2,\"name\":\"equipment22\"}]}";
}
return ResultModel.of(equipments);
}
乐观锁机制解决多层嵌套异步ajax问题的更多相关文章
- Java并发编程(05):悲观锁和乐观锁机制
本文源码:GitHub·点这里 || GitEE·点这里 一.资源和加锁 1.场景描述 多线程并发访问同一个资源问题,假如线程A获取变量之后修改变量值,线程C在此时也获取变量值并且修改,两个线程同时并 ...
- 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)
该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...
- 十三: 悲观锁&乐观锁:解决丢失更新问题
悲观锁:认为丢失更新一定会出现,可以在查询的时候加入for update 认为丢失更新一定会出现,查询时: select * from account for update;for update : ...
- PHP.39-扩展-锁机制解决并发-MySQL锁、PHP文件锁
锁机制适用于高并发场景:高并发订单.秒杀…… apache压力测试 Mysql锁详解 语法 加锁:LOCK TABLE 表名1 READ|WRITE, 表名2 READ|WRITE ......... ...
- 用Promise解决多个异步Ajax请求导致的代码嵌套问题【转】
问题 前端小同学在做页面的时候,犯了个常见的错误:把多个Ajax请求顺序着写下来了,而后面的请求,对前面请求的返回结果,是有依赖的.如下面的代码所示: var someData; $.ajax({ u ...
- mybatis乐观锁实现,解决并发问题
银行两操作员同时操作同一账户就是典型的例子.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后提交.最后实际账户余额为100 ...
- 使用mysql乐观锁解决并发问题
案例说明: 银行两操作员同时操作同一账户.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后提交.最后实际账户余额为1000 ...
- [数据库锁机制] 深入理解乐观锁、悲观锁以及CAS乐观锁的实现机制原理分析
前言: 在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数据库都提供了锁机制,并引入了事务隔离级别的概念.数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务 ...
- 使用mysql乐观锁解决并发问题思路
本文摘自网络,仅供个人学习之用 案例说明: 银行两操作员同时操作同一账户.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后 ...
随机推荐
- Maths | 层次分析法(Analytic Hierarchy Process)
目录 1. 概述 2. AHP算法 2.1. 建立层级 2.2. 构造 成对 比较 矩阵 2.3. 成对比较矩阵的 一致性检验 与 层次单排序 2.4. 层次总排序 参考: (中文)https://z ...
- 2019浙大校赛--G--Postman(简单思维题)
一个思维水题 题目大意为,一个邮递员要投递N封信,一次从邮局来回只能投递K封.求最短的投递总距离.需注意,最后一次投递后无需返回邮局. 本题思路要点: 1.最后一次投递无需返回邮局,故最后一次投递所行 ...
- js基础知识:字面量 关键字和保留字
js中的字面量概念我的理解就是:字体表面的常量 如:数字 100, 字符串 "ssss"或'ssss' 布尔值:false ,正则 以及null对象. 这些都是常量. 关键字: ...
- File(File f, String child) File(String parent, String child)
(转载)File(File f, String child) 根据f 抽象路径名和 child 路径名字符串创建一个新 File 实例. f抽象路径名用于表示目录,child 路径名字符串用于表示目录 ...
- app -webkit-box-orient: vertical 打包后不显示
先说明问题是什么: -webkit-box-orient: vertical 这个属性在本地运行调试是存在的,但是打包后这个属性消失了: 解决办法: 1.将-webkit-box-orient: ve ...
- JS获取对象数据类型的方法
1.typeof: 语法:typeof 对象 或者 typeof(对象) 返回对象的数据类型:只有原始数据类型:boolean number string undefined function obj ...
- Python小练习之寻找101到200之间的素数
方法1:from math import * def primeNumber(start,end): num = 0 for i in range(start,end): flag = 0 for j ...
- autotrace执行计划中,统计信息详解
全表扫描是怎么扫描的? oracle最小的存储单位是block 物理上连续的block组成了extent(也就是说一个区中的所有块在物理上是连续的) 很多个extent组成了segment(一个seg ...
- CSRF 攻击(跨域攻击)
一.CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSR ...
- Javascript高级编程学习笔记(54)—— DOM2和DOM3(6)范围选择
范围 为了让开发人员更加方便地控制页面“DOM2级遍历和范围”模块定义了“范围”接口 通过该接口开发人员可以选择文档中的一个区域,而不必考虑元素的界限 在常规操作不能有效地修改文档时,使用范围往往可以 ...