异步问题
1. 设置setTimeout来延迟下一步操作的执行时间,来解决ajax网络请求和下一步操作的异步冲突。需要注意的是,
定时器的时间设置一定要大于等于网络请求的时间。
代码如下:
// 定义状态机
constructor(props, context) {
super(props, context);
this.state = {
content:null
}
}
//网络请求方法
Add = () => {
var formData = new FormData($("#userForm")[0]); // 定位到userForm表单,并将表单定位转为FormData对象
$.ajax({
url: '/add', //网络请求url地址
type: 'POST',
data: formData, //表单数据
cache: false,
contentType: false, //或者 contentType:multipart/form-data均可以,multipart/form-data表示可以上传下载文件(既可以发送文本数据,也支持二进制数据上载),表明传输的数据要用到多媒体传输协议,由于多媒体传输的都是大量的数据,所以规定上传文件必须是post方法;contentType默认为application/x-www-form-urlencoded不能上传文件
processData: false,
success: function (data) {
console.log('成功'); this.setState({content:'修改成功'})
}.bind(this),
error: function (xhr, status, err) {
}.bind(this)
});
}
//执行操作
this.add();
setTimeout(() => {
if(this.state.content=='修改成功'){alert('修改成功')}
else{alert('修改失败')}
}, 1000);
//如果不加1秒定时延迟,会直接进行判断,即未等网络请求结束便进行了判断
2. 设置ajax的async属性
async默认属性是true,表示异步执行, 如果需要同步请求,则修改成false
注意async为false的时候,这时候锁住了浏览器,用户其他操作都必须等到网络请求完成后才能执行。
/ 定义状态机
constructor(props, context) {
super(props, context);
this.state = {
content:null
}
}
//网络请求方法
Add = () => {
var formData = new FormData($("#userForm")[0]); // 定位到userForm表单,并将表单定位转为FormData对象
$.ajax({
url: '/add', //网络请求url地址
type: 'POST',
data: formData, //表单数据
async:false,
cache: false,
contentType: false, //或者 contentType:multipart/form-data均可以,multipart/form-data表示可以上传下载文件(既可以发送文本数据,也支持二进制数据上载),表明传输的数据要用到多媒体传输协议,由于多媒体传输的都是大量的数据,所以规定上传文件必须是post方法;contentType默认为application/x-www-form-urlencoded不能上传文件
processData: false,
success: function (data) {
console.log('成功'); this.setState({content:'修改成功'})
}.bind(this),
error: function (xhr, status, err) {
}.bind(this)
});
}
//执行操作
this.add();
if(this.state.content=='修改成功'){alert('修改成功')}
else{alert('修改失败')}
提高用户体验-beforeSend&complete
场 景:在ajax发送网络请求的时候,用户重复点击提交按钮,造成后台存储了重复的数据
解决方案:在提交ajax的时候,有全局事件和局部事件在执行,详情查看ajax-全局事件,
beforeSend和complete函数属于局部事件。
异步与同步操作下beforeSend和complete的区别:
var obj=0;
$.ajax({
url:"../data/test.txt",
contentType:"application/json",
type:"POST",
cache:false,
async:true,
beforeSend:function(){
$('#queryForm').hide();
},
success:function(result){
obj=result;
},
complete:function(){
}
});
console.log(obj);
});
}
async:true 这种情况是异步方式,当ajax发送请求前,会先执行ajax块中beforeSend里面的代码,如果beforeSend里面有Dom的操作,就可以立即对Dom进行渲染,当ajax发送请求后,在等待server端返回数据的过程中,程序会继续执行ajax外面的代码块,知道服务器返回正确的结果才会去执行success方法,因此,在执行success前,Dom隐藏,obj为0
async:flase 这时候ajax请求是同步的,这样的话,当ajax发送请求前,回西安之行ajax块中beforeSend路面的代码,如果beforeSend里面的代码有Dom操作,不会立即对Dom渲染,而是等到complete执行完成之后,才会渲染Dom,当ajax发送请求成功之后,才会执行ajax块外面的代码,因此,在执行完成complete之后,Dom才隐藏,obj=result
可以解决的场景:
1 防止重复数据
// 提交表单数据到后台处理
$.ajax({
type: "post",
data: studentInfo,
contentType: "application/json",
url: "/Home/Submit",
beforeSend: function () {
// 禁用按钮防止重复提交
$("#submit").attr({ disabled: "disabled" });
},
success: function (data) {
if (data == "Success") {
//清空输入框
clearBox();
}
},
complete: function () {
$("#submit").removeAttr("disabled");
},
error: function (data) {
console.info("error: " + data.responseText);
}
});
2 模拟Toast效果
ajax请求服务器加载数据列表的时候显示loading('加载中,请稍后......')
$.ajax({
type: "post",
contentType: "application/json",
url: "/Home/GetList",
beforeSend: function () {
$("loading").show();
},
success: function (data) {
if (data == "Success") {
// ...
}
},
complete: function () {
$("loading").hide();
},
error: function (data) {
console.info("error: " + data.responseText);
}
});