zoukankan      html  css  js  c++  java
  • 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 });

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

  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/ZheOneAndOnly/p/10549995.html
Copyright © 2011-2022 走看看