前言

  在项目中我们通常需要使用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("&nbsp;&nbsp;&nbsp;&nbsp;<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问题的更多相关文章

  1. Java并发编程(05):悲观锁和乐观锁机制

    本文源码:GitHub·点这里 || GitEE·点这里 一.资源和加锁 1.场景描述 多线程并发访问同一个资源问题,假如线程A获取变量之后修改变量值,线程C在此时也获取变量值并且修改,两个线程同时并 ...

  2. 巧用MySQL InnoDB引擎锁机制解决死锁问题(转)

    该文会通过一个实际例子中的死锁问题的解决过程,进一步解释innodb的行锁机制 最近,在项目开发过程中,碰到了数据库死锁问题,在解决问题的过程中,笔者对MySQL InnoDB引擎锁机制的理解逐步加深 ...

  3. 十三: 悲观锁&乐观锁:解决丢失更新问题

    悲观锁:认为丢失更新一定会出现,可以在查询的时候加入for update 认为丢失更新一定会出现,查询时: select * from account for update;for update :  ...

  4. PHP.39-扩展-锁机制解决并发-MySQL锁、PHP文件锁

    锁机制适用于高并发场景:高并发订单.秒杀…… apache压力测试 Mysql锁详解 语法 加锁:LOCK TABLE 表名1 READ|WRITE, 表名2 READ|WRITE ......... ...

  5. 用Promise解决多个异步Ajax请求导致的代码嵌套问题【转】

    问题 前端小同学在做页面的时候,犯了个常见的错误:把多个Ajax请求顺序着写下来了,而后面的请求,对前面请求的返回结果,是有依赖的.如下面的代码所示: var someData; $.ajax({ u ...

  6. mybatis乐观锁实现,解决并发问题

    银行两操作员同时操作同一账户就是典型的例子.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后提交.最后实际账户余额为100 ...

  7. 使用mysql乐观锁解决并发问题

    案例说明: 银行两操作员同时操作同一账户.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后提交.最后实际账户余额为1000 ...

  8. [数据库锁机制] 深入理解乐观锁、悲观锁以及CAS乐观锁的实现机制原理分析

    前言: 在并发访问情况下,可能会出现脏读.不可重复读和幻读等读现象,为了应对这些问题,主流数据库都提供了锁机制,并引入了事务隔离级别的概念.数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务 ...

  9. 使用mysql乐观锁解决并发问题思路

    本文摘自网络,仅供个人学习之用 案例说明: 银行两操作员同时操作同一账户.比如A.B操作员同时读取一余额为1000元的账户,A操作员为该账户增加100元,B操作员同时为该账户扣除50元,A先提交,B后 ...

随机推荐

  1. Windows服务器开发和Linux服务器软件开发的区别

    大型网页游戏服务器开发(Windows+Linux) 进程监听 负载均衡 数据库分发 MapGIS IGServer(Java C++)

  2. JS入门经典第四章总结

    charAt():该函数有一个参数,即选择哪一个位置上的参数.返回值就是该位置上的字符. charCodeAt():该函数有一个参数,即选择哪一个位置上的参数.返回值是该位置字符在Unicode字符集 ...

  3. Python TypeError: 'module' object is not callable 原因分析

    今天尝试使用pprint进行输出,语句为 >>>import pprint >>>pprint(people) 结果报错,TypeError: 'module' o ...

  4. HTML标签的绝对路径和相对路径

    我在javaweb中写json的Demo的时候遇到了这个问题,图片一一直取不出来,查了好久终于解决了,所以现在记录一下. 绝对路径: 其实很容易理解,如果你是一个普通的项目,那就是它在你电脑里真实存在 ...

  5. STM32学习笔记

    1.32位即表示32个二进制位(0/1)即32根线,每根线可以表示0/1两种状态,所以可以表示2^32=4GB的大小,CM3 采用了哈佛结构,拥有独立的指令总线和数据总线,可以让取指与数据访问并行不悖 ...

  6. IDEA的Database表的基本操作

    1.创建表 方法一:直接创建:右键-new-table 方法2: 参考别的表,直接用语句,右键-DDL and Sources- 然后直接在控制台修改 修改后直接运行,表就建好了 2.备份表 先用上面 ...

  7. Python之旅Day13 JavaScript与DOM部分

    JavaScript部分 JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应的代码,浏览器就可以解释并做出相应的 ...

  8. 2017-12-04 编写Visual Studio Code插件初尝试

    参考官方入门: Your First Visual Studio Code Extension - Hello World 源码在: program-in-chinese/vscode_helloWo ...

  9. 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务)

    [源码下载] 背水一战 Windows 10 (119) - 后台任务: 后台下载任务(任务分组,组完成后触发后台任务) 作者:webabcd 介绍背水一战 Windows 10 之 后台任务 后台下 ...

  10. 816. Ambiguous Coordinates

    We had some 2-dimensional coordinates, like "(1, 3)" or "(2, 0.5)".  Then, we re ...