函数内的ajax同步请求导致遮罩层失效、或者导致loading正在加载提示失效问题「建议收藏」

函数内的ajax同步请求导致遮罩层失效、或者导致loading正在加载提示失效问题「建议收藏」功能需求编写点击按钮,弹出loading遮罩层提示正在加载中…,同时查询后台信息,拼接数据后渲染到列表时,为了保障渲染时,列表中的数据已经拼接完成。所以在for循环中使用同步ajax进行请求,在success方法中进行拼接。functionshowPrintJobList(){ varloadingTip=$(‘#loading’); loadingTip.show(); for(vari=0;i<rwid.length;i++){ $.ajax({ url:x

大家好,欢迎来到IT知识分享网。

功能需求

编写点击按钮,弹出loading遮罩层提示正在加载中…,同时查询后台信息,拼接数据后渲染到列表时,为了保障渲染时,列表中的数据已经拼接完成。所以在for循环中使用同步ajax进行请求,在success方法中进行拼接。

function showPrintJobList(){ 
   
	var loadingTip = $('#loading');
	loadingTip.show();
	for(var i = 0;i < rwid.length;i++){ 
   
		$.ajax({ 
   
			url: xxxxx,
			async: false,  //默认异步,为保证数据完整和顺序使用同步请求
			type: 'POST',
			data:{ 
   
				xxx: xxx
			},
			dataType: 'json',
	      	success: function(result) { 
   
				//.....循环拼接结果,弹窗显示列表:$('#rwlist').show();
			},
			error: function(err){ 
   
				console.log(err);
			}
		});
	}
	loadingTip.hide();
	$('#rwlist').show();
}

IT知识分享网

问题信息

点击按钮后,遮罩层没有弹出,而是等待表单渲染完成后,看到一闪而过的遮罩层。

问题原因async: false

ajax同步请求在运行的时候,浏览器的UI、Dom元素渲染会被阻塞。所以当点击事件触发showPrintJobList函数时,loading.show()是有被加载到浏览器的js运行线程中,但是运行到ajax同步请求时,会将loading.show()阻塞执行,等到同步ajax请求完了,才会运行。然后同步ajax已经请求完了,然后直接被隐藏,然后显示列表。所以会看到一闪而过的loading遮罩层

解决方法

一、使用async wait关键字
二、使用JQuery的Deferred对象和$.when().done().fail()

async/await关键字
  1. 标识所修饰的函数存在异步代码,函数内部可用await关键字修饰异步过程变为同步。函数内部也可以全部为同步代码。
  2. 非阻塞:async所标识的函数内存在异步代码,会等待异步代码执行完,但是async函数本身会马上返回,不会阻塞当前js工作主线程,可以简单认为,async函数工作在主线程,同步执行,不会阻塞界面渲染,async函数内部由await关键字修饰的异步过程,工作在相应的协程上,会阻塞等待异步任务的完成再返回;

代码修改如下:

IT知识分享网async function showPrintJobList(){ 
   
	var loadingTip = $('#loading');
	loadingTip.show();
	for(var i = 0;i < rwid.length;i++){ 
   
		await $.ajax({ 
      //使用await关键字修饰异步请求,保证数据顺序完整
			url: xxxxx,
			async: true,  //有await关键字,ajax请求修改为异步
			type: 'POST',
			data:{ 
   
				xxx: xxx
			},
			dataType: 'json',
	      	success: function(result) { 
   
				//.....循环拼接结果,弹窗显示列表:$('#rwlist').show();
			},
			error: function(err){ 
   
				console.log(err);
			}
		});
	}
	loadingTip.hide();
	$('#rwlist').show();
}

或者使用JQuery的Deferred对象和$.when().done().fail()使异步请求同步执行,同时不阻塞主线程。

var dataList = [];
function showPrintJobList(){ 
   
	var defer = $.Deferred();
	for(var i = 0;i < rwid.length;i++){ 
   
		$.ajax({ 
      
			url: xxxxx,
			async: true,  //使用Deferred对象,ajax请求修改为异步
			type: 'POST',
			data:{ 
   
				xxx: xxx
			},
			dataType: 'json',
	      	success: function(result) { 
   
				//dataList保存结果
				dataList.push(result);
				defer.resolve(dataList);
			},
			error: function(err){ 
   
				defer.reject(err);
			}
		});
	}
	return defer;
}

$('button#showList').click(function(){ 
   
	var loadingTip = $('#loading');
	loadingTip.show();
	$.when(showPrintJobList()).done(function(data){ 
   
        //循环拼接data中的list中的数据
        loadingTip.hide();
		$('#rwlist').show();
    }).fail(function(){ 
   
    	console.log(err);
    });
}

原理解析

浏览器中一般会运行UI线程、JS线程以及事件触发线程。
在上述上述代码中,loading.show()方法涉及到dom树的更新,所以被加载到了UI线程执行任务中。但是后面的ajax同步请求,因为不是异步的所以浏览器不会重新新增一个线程进行请求,而是直接放在js线程中阻塞其他线程执行。所以UI线程不能执行loading.show()方法。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/6924.html

(0)
上一篇 2023-01-03 09:55
下一篇 2023-01-03 09:55

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信