jQuery使用(十二):工具方法之ajax的无忧回调(优雅的代码风格)

时间:2023-03-09 00:54:40
jQuery使用(十二):工具方法之ajax的无忧回调(优雅的代码风格)
  • jQuery.ajax()方法的应用
  • jQuery.ajax()的无忧回调(优雅的代码风格)

一、jQuery.ajax()方法的应用

jQuery.ajax()实质上就是在ajax的基础上进行了封装,将参数设置,方法调用,数据传输,响应的回调函数等都封装到一个对象中,然后使用这个对象作为jQurey.ajax()的参数调用实现统一配置执行的效果。

jQuery.ajax(object)中的object的常用属性及设置:

  • url:请求地址
  • type:HTTP的请求方法
  • success:请求成功的处理函数(响应的数据会被转换成对象传入处理函数)
  • error:当请求失败的处理函数,会传入一个提示对象,其中obj.status为状态码,obj.statusText表示状态说明。
  • complete:请求完成以后(无论成功还是失败)的处理函数
  • context:改变函数上下文
  • timeout:设置本地的请求超时时间(以毫秒计)。
  • async:请求采用异步还是同步执行(默认异步)
  • dataType:预期的服务器响应的数据类型(json)。

1.Easy Mock模拟jQuery.ajax()请求:

 $.ajax({
url:'https://easy-mock.com/mock/5c0b4a876162b83fe0a50cb9/person',
type:"GET",
success:function(res){
$.each(res.data,function(index,ele){
console.log(ele);
})
},
error:function(e){
if(e.status == 404){
console.log("我找不到主人要的宝贝。。。哇呜。。。");
}
},
complete:function(){
console.log("我完成了任务,快夸我,夸我的人都长得好。");
}
});

2.使用context改变函数执行的上下文示例:

 //html
<div class="wrapper"></div>
//js
$.ajax({
url:'https://easy-mock.com/mock/5c0b4a876162b83fe0a50cb9/person',
type:"GET",
success:function(res){
console.log(this);////init [div.wrapper, prevObject: init(1), context: document, selector: ".wrapper"]
},
context:$('.wrapper'),
complete:function(){
console.log(this)//init [div.wrapper, prevObject: init(1), context: document, selector: ".wrapper"]
}
});

二、jQuery.ajax()的无忧回调(优雅的代码风格)

通过第一部分的分析,好像jQuery.ajax已经全部学会了,no...

对于一个简单的网络请求来说,第一部分无可厚非已经足以,但是在实际开发中,复杂的需求伴随着的是复杂的代码结构和网络情况,如果存在多个网络请求嵌套请求的情况,代码会出现死亡三角的复杂区域,对于后期维护会造成非常大的麻烦。为了更友好的开发维护,jQuery.ajax提供了强大的解决方案,就是jQuery.ajax请求会返回一个Deferred.promise()方法,这个方法提供了友好的ajax不同完成状态的回调函数的添加接口。可能到这里你还不知道我在说什么,接下来看下面这个需求的由ajax产生的死亡三角和其解决方案的两份代码你就明白了,由于篇幅比较大,我将需求和死亡三角代码折叠,提供最后优雅的代码展示:

 <!-- 一、基础说明
code/ code为0时表示正常状态,msg为Ok
msg / code为非0时表示异常状态,msg为error
data/ 接口返回实体数据
二、实体对象
power:
名称 / 类型/ 备注
Power/ String/ 权限
movieList:
名称 / 类型 / 备注
name / String/ 电影名字
poster/ String/ 电影封面
id / String/ 电影id
movieInfo:
名称 / 类型 / 备注
name / String / 电影名字
poster / String / 电影封面
direct / String / 导演
screewriter/ Array<string>/ 编剧
mainActior / Array<string>/ 主演
gut / String / 剧情
三、接口文档
1.权限
BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie
URL:/power
Type:POST
Request:
名称 / 类型 / 备注
Username/ String/ 用户名
Password/ String/ 密码
Response:
{
code:0
msg:OK
data:power
} 2.电影列表
BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie
URL:/movieList
Type:GET
Response:
{
code:0
msg:OK
data:Array <movieList>
} 3.电影详情
BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie
URL:/movieInfo
Type:GET
Request:
名称 / 类型 / 备注
movieId/ Number/ 电影的ID
Response:
{
code:0
msg:OK
data:movieInfo
}

文档

 <style type="text/css" media="screen">
*{
padding: 0px;
margin: 0px auto;
}
.tpl{
display: none;
}
.wrapper{
overflow: hidden;
border: 2px solid black;
width: 600px;
margin: 100px auto 0px;
}
.movieSection{
float: left;
width: 180px;
height: 180px;
padding: 10px;
}
.movieSection img{
width: 100%;
height: 150px;
cursor: pointer;
}
.movieSection h3{
height: 30px;
}
</style>
<div class="wrapper">
<div class="tpl">
<img src="">
<h3 class="movieName"></h3>
</div>
</div>
<script>
//
$.ajax({
url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
type:"POST",
data:{
username:"cst",
password:"123123"
},
success:function(res){
if(res.data.power == 'root'){
//vip 网络地址发送请求
$.ajax({
url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
type:'GET',
success:function(res){
var data = res.data;
var $Wrapper = $('.wrapper');
$.each(data,function(index,ele){
// ele.name ele.poste
var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection');
$MovieSection.data({id:ele.id}).on('click',function(){
$.ajax({
url:"https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo",
type:'GET',
data:{
movieId:$(this).data('id')
},
success:function(res){
var data = res.data;
var direct = data.direct;
var gut = data.gut;
var mainActor = data.mainActor;
var screenWriter = data.screenwriter;
var htmlStr = '<div class="mask">\
<p>导演:'+ direct +'</p>\
<p>主演:'+ mainActor.reduce(function(prev,curv){
prev += curv + "&nbsp;&nbsp;";
return prev;
}) +'</p>\
<p>编剧:'+ screenWriter.reduce(function(prev,curv){
prev += curv + "&nbsp;&nbsp;";
return prev;
}) +'</p>\
<p>剧情:'+ gut +'</p>\
</div>';
console.log(htmlStr);
$(htmlStr).appendTo('body')
.css({position:'absolute',left:$(window).outerWidth()/2,bottom:100,width:400,marginLeft:-200,top:505});
}
});
}).children()
.eq(0).attr('src',ele.poster)
.next().text(ele.name);
$Wrapper.append($MovieSection);
});
}
});
}else{
//非vip
}
}
});
</script>

回调地狱

通过上面的【回调地狱】就有一个值得思考的问题了,如何避免这种代码带来的负面影响呢?可以参考另一篇博客:jQuery使用():Deferred有状态的回调列表(含源码)如果要完整的解析整个jQuery.ajax解决这种【回调地狱】的问题就相当于要将jQuery.Deferred的实现机制全部解析一篇,所以这里就不再赘述了。用最简单的描述就是当通过jQuery.ajax()创建一个请求时,jQuery.ajax()会返回一个jQuery.Deferred对象,更准确的说是会返回Deferred.promise对象,这样就可以通过在外部接收这个对象,promise对象上包含了一系列的异步状态的回调函数的注册方法done、fail、progress、then。这些方法的具体使用参考前面那篇博客,下面我通过then方法来改造上面那段【回调地狱】的代码:

 $.ajax({
url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
type:"POST",
data:{
username:"cst",
password:"123123"
}
//请求会员资源--电影列表
}).then(function(res){
if(res.data.power == 'root'){
//vip 网络地址发送请求
return $.ajax({
url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
type:'GET'
});
}
//
}).then(function(res){
var data = res.data;
var $Wrapper = $('.wrapper');
var df = $.Deferred();
$.each(data,function(index,ele){
// ele.name ele.poste
var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection');
$MovieSection.data({id:ele.id})
.on('click',function(){
df.resolve($(this));
})
.children()
.eq(0).attr('src',ele.poster)
.next().text(ele.name);
$Wrapper.append($MovieSection);
});
return df.promise();
}).then(function(dom){
return $.ajax({
url:"https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo",
type:'GET',
data:{
movieId:dom.data('id')
}
})
}).then(function(res){
console.log(res);
var data = res.data;
var direct = data.direct;
var gut = data.gut;
var mainActor = data.mainActor;
var screenWriter = data.screenwriter;
var htmlStr = '<div class="mask">\
<p>导演:'+ direct +'</p>\
<p>主演:'+ mainActor.reduce(function(prev,curv){
prev += curv + "&nbsp;&nbsp;";
return prev;
}) +'</p>\
<p>编剧:'+ screenWriter.reduce(function(prev,curv){
prev += curv + "&nbsp;&nbsp;";
return prev;
}) +'</p>\
<p>剧情:'+ gut +'</p>\
</div>';
console.log(htmlStr);
$(htmlStr).appendTo('body')
.css({position:'absolute',left:$(window).outerWidth()/2,bottom:100,width:400,marginLeft:-200,top:505});
});

上面改造后的代码也就是开发中需要遵循的单一职责原则。