前言

  在项目中我们通常需要使用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. Python开发——13.操作系统、进程和线程

    一.操作系统 1.定义 操作系统是用来协调.管理和控制计算机硬件和软件资源的系统程序,它位于硬件和应用程序之间.操作系统运行在内核态,拥有对所有硬件的完全访问权,可以执行机器能够运行的任何指令.软件的 ...

  2. ionic3 百度地图插件定位 问题

    每次用 cordova-pluin-baidumaploaction    每调用一次  他只会执行一次 我想循环  但是每次都会初始化   把插件的java代码98行注释就好了

  3. _ZNote_Qt_QDialog_修改button名称

    #include <QPushButton> ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Run ...

  4. Leetcode(二)两数相加

    两数相加 题目描述 给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字. 如果,我们将这两个数相加起来,则会返回一个新的链 ...

  5. -实现 LFU 缓存算法

    -实现 LFU 缓存算法, 设计一个类 LFUCache,实现下面三个函数 + 构造函数: 传入 Cache 内最多能存储的 key 的数量 + get(key):如果 Cache 中存在该 key, ...

  6. objec类中方法介绍

    java.lang.object,是Java中所有类(当然Object类除外)的终极父类,其中数组也继承了Object类,但是接口是不继承Object类的. Object中方法如下(11个): Cla ...

  7. PMP:6.项目进度管理

    项目管理包括为项目管理项目按时完成所需的各个过程:

  8. [转]Virtio balloon

    http://rwmj.wordpress.com/2010/07/17/virtio-balloon/ After someone asked me a question about “balloo ...

  9. WSGI and Paste学习笔记

    The Problem Lots of web frameworks Zope, Quixote, Webware, SkunkWeb and Twisted Web etc Applications ...

  10. cef3:禁止win10高dpi下cef对内部网页进行缩放

    1.使用命令行参数 //禁止cef进行dpi缩放 command_line->AppendSwitchWithValue("--force-device-scale-factor&qu ...