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()请求:

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

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

 1 //html
 2 <div class="wrapper"></div>
 3 //js
 4 $.ajax({
 5     url:'https://easy-mock.com/mock/5c0b4a876162b83fe0a50cb9/person',
 6     type:"GET",
 7     success:function(res){
 8         console.log(this);////init [div.wrapper, prevObject: init(1), context: document, selector: ".wrapper"]
 9     },
10     context:$('.wrapper'),
11     complete:function(){
12         console.log(this)//init [div.wrapper, prevObject: init(1), context: document, selector: ".wrapper"]
13     }
14 });

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

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

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

 1 <!-- 一、基础说明
 2 code/    code为0时表示正常状态,msg为Ok
 3 msg /    code为非0时表示异常状态,msg为error
 4 data/    接口返回实体数据
 5 二、实体对象
 6 power:
 7 名称    /    类型/        备注
 8 Power/    String/      权限
 9 movieList:
10 名称      / 类型  /  备注
11 name  /    String/    电影名字
12 poster/    String/    电影封面
13 id    /    String/    电影id
14 movieInfo:
15 名称           /    类型             /  备注
16 name       /    String       /    电影名字
17 poster     /    String       /    电影封面
18 direct     /    String       /    导演
19 screewriter/    Array<string>/    编剧
20 mainActior /    Array<string>/    主演
21 gut           /    String         /  剧情
22 三、接口文档
23 1.权限
24 BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie
25 URL:/power
26 Type:POST
27 Request:
28 名称        /   类型      / 备注
29 Username/    String/    用户名
30 Password/    String/    密码
31 Response:
32 {
33     code:0
34     msg:OK
35     data:power
36 }
37 
38 2.电影列表
39 BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie
40 URL:/movieList
41 Type:GET
42 Response:
43 {
44     code:0
45     msg:OK
46     data:Array <movieList>
47 } 
48 
49 3.电影详情
50 BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie
51 URL:/movieInfo
52 Type:GET
53 Request:
54 名称       /    类型      /  备注
55 movieId/    Number/     电影的ID
56 Response:
57 {
58     code:0
59     msg:OK
60     data:movieInfo
61 }
文档
 1 <style type="text/css" media="screen">
 2     *{
 3         padding: 0px;
 4         margin: 0px auto;
 5     }
 6     .tpl{
 7         display: none;
 8     }
 9     .wrapper{
10         overflow: hidden;
11         border: 2px solid black;
12         width: 600px;
13         margin: 100px auto 0px;
14     }
15     .movieSection{
16         float: left;
17         width: 180px;
18         height: 180px;
19         padding: 10px;
20     }
21     .movieSection img{
22         width: 100%;
23         height: 150px;
24         cursor: pointer;
25     }
26     .movieSection h3{
27         height: 30px;
28     }
29 </style>
30 <div class="wrapper">
31     <div class="tpl">
32         <img src="">
33         <h3 class="movieName"></h3>
34     </div>
35 </div>
36 <script>
37     //
38     $.ajax({
39         url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
40         type:"POST",
41         data:{
42             username:"cst",
43             password:"123123"
44         },
45         success:function(res){
46             if(res.data.power == 'root'){
47                 //vip 网络地址发送请求
48                 $.ajax({
49                     url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
50                     type:'GET',
51                     success:function(res){
52                         var data = res.data;
53                         var $Wrapper = $('.wrapper');
54                         $.each(data,function(index,ele){
55                             // ele.name ele.poste
56                             var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection');
57                             $MovieSection.data({id:ele.id}).on('click',function(){
58                                 $.ajax({
59                                     url:"https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo",
60                                     type:'GET',
61                                     data:{
62                                         movieId:$(this).data('id')
63                                     },
64                                     success:function(res){
65                                         var data = res.data;
66                                         var direct = data.direct;
67                                         var gut = data.gut;
68                                         var mainActor = data.mainActor;
69                                         var screenWriter = data.screenwriter;
70                                         var htmlStr = '<div class="mask">
71                                             <p>导演:'+ direct +'</p>
72                                             <p>主演:'+ mainActor.reduce(function(prev,curv){
73                                                 prev += curv + "&nbsp;&nbsp;";
74                                                 return prev;
75                                             }) +'</p>
76                                             <p>编剧:'+ screenWriter.reduce(function(prev,curv){
77                                                 prev += curv + "&nbsp;&nbsp;";
78                                                 return prev;
79                                             }) +'</p>
80                                             <p>剧情:'+ gut +'</p>
81                                         </div>';
82                                         console.log(htmlStr);
83                                         $(htmlStr).appendTo('body')
84                                             .css({position:'absolute',left:$(window).outerWidth()/2,bottom:100,400,marginLeft:-200,top:505});
85                                     }
86                                 });
87                             }).children()
88                                 .eq(0).attr('src',ele.poster)
89                                     .next().text(ele.name);
90                             $Wrapper.append($MovieSection);
91                         });
92                     }
93                 });
94             }else{
95                 //非vip
96             }
97         }
98     });
99 </script>
回调地狱

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

 1 $.ajax({
 2     url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power',
 3     type:"POST",
 4     data:{
 5         username:"cst",
 6         password:"123123"
 7     }
 8 //请求会员资源--电影列表
 9 }).then(function(res){
10     if(res.data.power == 'root'){
11         //vip 网络地址发送请求
12         return $.ajax({
13             url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList',
14             type:'GET'
15         });
16     }
17 //
18 }).then(function(res){
19     var data = res.data;
20     var $Wrapper = $('.wrapper');
21     var df = $.Deferred();
22     $.each(data,function(index,ele){
23         // ele.name ele.poste
24         var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection');
25         $MovieSection.data({id:ele.id})
26             .on('click',function(){
27                 df.resolve($(this));
28             })
29                 .children()
30                     .eq(0).attr('src',ele.poster)
31                         .next().text(ele.name);
32         $Wrapper.append($MovieSection);
33     });
34     return df.promise();
35 }).then(function(dom){
36     return $.ajax({
37         url:"https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo",
38         type:'GET',
39         data:{
40             movieId:dom.data('id')
41         }
42     })
43 }).then(function(res){
44     console.log(res);
45     var data = res.data;
46     var direct = data.direct;
47     var gut = data.gut;
48     var mainActor = data.mainActor;
49     var screenWriter = data.screenwriter;
50     var htmlStr = '<div class="mask">
51         <p>导演:'+ direct +'</p>
52         <p>主演:'+ mainActor.reduce(function(prev,curv){
53             prev += curv + "&nbsp;&nbsp;";
54             return prev;
55         }) +'</p>
56         <p>编剧:'+ screenWriter.reduce(function(prev,curv){
57             prev += curv + "&nbsp;&nbsp;";
58             return prev;
59         }) +'</p>
60         <p>剧情:'+ gut +'</p>
61     </div>';
62     console.log(htmlStr);
63     $(htmlStr).appendTo('body')
64         .css({position:'absolute',left:$(window).outerWidth()/2,bottom:100,400,marginLeft:-200,top:505});
65 });

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

原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/10549995.html