zoukankan      html  css  js  c++  java
  • jquery Deferred使用经验

    这周做了个小活动(http://aoqi.100bt.com/zt-2016duanzi/index.html),刚开始时候没看好需求,逻辑都写一块了

    最后各种坑要填补,从中也获取了些经验和教训,下面说说这里会用到的$.Deferred;

    关于jquery里面的deferred的基本使用方法,阮一峰大婶已经有文章说明了,链接如下:

    http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

    这里就说说里面没提及的吧:

    页面中逻辑比较麻烦的就是获奖名单的渲染问题,如下图

    这里需要的逻辑是:

    1、获取时间,判断是否有活动过了投票时间,没有则不可点击,页面不渲染

    2、过来时间后,判断能否获取到获奖名单,获取到就渲染次阶段的页面,获取不到则渲染前一个阶段的页面,

      前一个阶段的页面还是获取不到则往前回溯,如果到第一个阶段还是没有则页面不渲染。

    假设四个页面对应的获奖名单是1.html、2.html、3.html、4.html;

    假如此时有时间判断活动时间已经在第四阶段,即是前三个阶段都结束,我们的实现逻辑或许是

    $.get('3.html').done(function(){
        //渲染页面
    }).fail(function (argument) {
        $.get('2.html').done(function (argument) {
            //渲染页面
        }).fail(function (argument) {
            function (argument) {
                $.get('1.html').done(function (argument) {
                    // 渲染页面
                }).fail(function (argument) {
                    // 不渲染页面
                })
            }
        })
    })

    这是很不可取的,在每个不同的阶段都要嵌套一次,而且每个请求都要等上一个请求发完才发,太慢了。。。

    于是就改成类似下面的

    var linkArr = ['1.html','2.html','3.html','4.html']
    $nav.each(function(index, el) {
        var $self = $(this);
        $.get(index+'.html').done(function (argument) {
             $self.text('获奖名单出来了')
         }).fail(function (argument) {
             $self.addClass('graynav').text('敬请期待');
         });
    });

    能“并行”地发出多个请求,看似不错,然后在添加点击渲染事件,点击不同的nav渲染已经出来的相应获奖名单,嗯,这也是逻辑上需要的

    $('.aCommon_nav').click(function(event) {
        if($(this).hasClass('graynav')){
            return false;
        }
        var i = $('aCommon_nav').index($(this));
        $.get(linkarr[i], function(data) {
            $inforWrap.html(data)
        });
    });

    这时候,我们只需在“并发”请求结束后调用最后一个可点的nav就完成了。。真赞

    可是安装现在这种写法,我们并不能判断是否已经完成了请求,或许需要维护个全局变量num,在每次fail和done再加1,当num等于需要发送的个数之后再调用函数

    var linkArr = ['1.html','2.html','3.html','4.html']
    var i = 0;
    $nav.each(function(index, el) {
        var $self = $(this);
        if($self.attr('xxx')<=timenum){//由时间判断出的是已经结束的标志
            $.get(index+'.html').done(function (argument) {
                 i++;
                 $self.text('获奖名单出来了');
                 if(i==LEN){
                     //DoClickEvent()
                 }
             }).fail(function (argument) {
                  i++;
                 $self.addClass('graynav').text('敬请期待');
                  if(i==LEN){
                     //DoClickEvent()
                 }
             });
         }
    });

    此时就已经基本完成了此次逻辑了,但是代码实在太糙,需要改进下,下面就用when来完成吧~

    var linkArr = ['1.html','2.html','3.html','4.html'],
        deferredArr = [];
    $('.aCommon_nav').each(function(index, el) {
        var $self = $(this);
        if($self.attr('xxx')<=timenum){//由时间判断出的是已经结束的标志
            deferredArr.push($.get(index+'.html').done(function (argument) {
                 $self.text('获奖名单出来了');
             }).fail(function (argument) {
                 $self.addClass('graynav').text('敬请期待');
             }))    
         }
    });
    
    $.when.apply(null,deferredArr).always(function(arg){
        $('.aCommon_nav:not(.garynav)').last().click();
    })

    这时候,貌似完成了这个逻辑,but,调试之后发现有时候先执行完done,然后fail然后always然后又done,貌似这顺序有些乱来了。。。

    然而我们希望的是先done或者fail最后执行always。

    发现原因是绑定顺序导致的,于是发现了两条路走,

    第一条,把done和fail逻辑都写在always里面,如下

    $.when.apply(null,defferredArr).always(function(arg){
        $.each(arguments, function(index, val) {
            val.done(function (argument) {
                 $self.text('获奖名单出来了');
             }).fail(function (argument) {
                 $self.addClass('graynav').text('敬请期待');
             })
        });
        $('.aCommon_nav:not(.garynav)').last().click();
    })

    这感觉好赞,deferred的回调函数都写一块了,维护起来也开心。

    但是当deferredArr里面只有一个元素的时候,发现报错了,好尴尬,只能断点看看,

    发现always回调函数里面的arguments竟然是一个数组,第一项是请求返回的数据,第二个是返回状态,第三个是此次请求的deferred对象,

    于是我们要加个判断,或加个try.catch包裹着done和fail,代码就不贴了,是在太糊弄了。

    第二条路,使用setTimeout的黑魔法

    var linkArr = ['1.html','2.html','3.html','4.html'],
        deferredArr = [];
    $('.aCommon_nav').each(function(index, el) {
        var $self = $(this);
        if($self.attr('xxx')<=timenum){//由时间判断出的是已经结束的标志
            deferredArr.push($.get(index+'.html').done(function (argument) {
                 $self.text('获奖名单出来了');
             }).fail(function (argument) {
                 $self.addClass('graynav').text('敬请期待');
             }))    
         }
    });
    
    $.when.apply(null,deferredArr).always(function(arg){
        setTimeout(function (argument) {
            $('.aCommon_nav:not(.garynav)').last().click();
        },0)
    })

    于是这个业务也完成了,废话也讲完了

    
    
    
  • 相关阅读:
    重构29-Remove Middle Man(去掉中间人)
    重构30-Return ASAP(尽快返回)
    重构26-Remove Double Negative(去掉双重否定)
    yaml语法学习3
    运行原理探究2
    SpringBoot简介 1
    SpringMVC项目所引用的一切依赖jar包和自定义设置
    2020/07/03 初始mybatis
    json数据格式字符串在java中的转移
    项目中遇到的一些异常
  • 原文地址:https://www.cnblogs.com/peace1/p/5594638.html
Copyright © 2011-2022 走看看