长轮询

长轮询的定义:

1、长轮询是传统轮询(短轮询)的一个翻版,即浏览器定时向服务器发送请求,看看有没有数据更新

2、页面发起一个到服务器的请求,然后服务器一直保持连接打开,直到有数据可发送。发送完数据之后,浏览器关闭连接,随即又发起一个到服务器的新请求。这一过程在页面打开期间一直持续不断。

长轮询和短轮询的相同点:浏览器都要在接收数据之前,先发起对服务器的连接

长轮询和短轮询的不同点:最大的区别在于服务器如何发送数据

 短轮询是服务器立即发送响应,无论数据是否有效

 长轮询是等待发送响应。

在前端和后台都会有个超时设置

在前端超时的话,浏览器又会向服务器发起一个请求。

在后台超时的话,服务器会向浏览器发送超时信息。


使用ajax技术,使服务器端和客户端之间建立连接,客户端发送请求,服务器端隔一定时间检查数据库是否有变动,没有变动,返回给客户端的数据为空,即可以是data='',还可能有个提示信息的返回变量msg='超时'。当检查到数据变动了,则服务器端返回数据,data='数据',msg='成功',客户端则做相应处理,处理完立即再次调用函数,与服务器端保持连接;服务器端会设定一定的时间,当超过这个时间数据库没有变化,就向客户端返回超时的信息,让客户端做处理,然后在建立连接关系。无论成功还是失败,都要在此次进行长轮询。


下面这个例子是轮询红包的状态变化:status=0,显示倒计时;status=1,处于抢红包状态;status=2,如果还有下一轮红包活动,则提示还有下一轮红包活动;如果没有下一轮抢红包活动,则显示活动已经结束。一进来该页面,就要显示相应状态的界面信息,然后处理当前有效的红包,才进入长轮询函数。

思路如下:

1、设置变量:

      current_redbag用于存储当前有效的红包活动信息,redbags存储所有红包活动信息。

2、函数requestRedbags(activity_id)的作用是根据活动的id号,前端向后台请求该活动的红包信息,并将请求到的红        包信息全部保存在全局变量redbags里面。

3、函数getAvailableRedbag()获取当前有效的红包,若没有有效的红包,则返回null

4、函数handleRedbag(redbag),处理当前有效的红包,即根据当前有效红包的status来进行相应的处理

5、函数check_redbag_status(redBagId,oldStatus,timeOut,startTime) 是检查红包状态变化的长轮询,参数redBagId        是当前该轮红包的id,oldStatus是上次红包的状态,timeOut超时的时间,startTime是开始摇红包开始的时间,          用 于倒计时的。无论成功还是失败,都要在此次进行长轮询

$(function() {
    var SHAKE_THRESHOLD = 1800;
    var last_update = 0;
    var x = y = z = last_x = last_y = last_z = 0;
    var num = 0;                    
    var shake_status = 0;                                    //0:未开始,1:正在进行 2:已结束                               
    var activity_id = "96";                                                                    
                                               
                                                            
   var current_redbag;                                                                       
   var redbags;                                                                               
   var time_distance = 0;//本地时间和服务器时间的差                                                                                                                                                                                                                                                             
   var numMax = 30;                                                                           
   
    // 请求红包列表,并对数据进行处理
    requestRedbags(activity_id);

    
    // --检测设备是否有摇一摇动作
    function deviceMotionHandler(eventData) {
        var acceleration = eventData.accelerationIncludingGravity;
        var curTime = new Date().getTime();
        shake_status = 1;
        if ((curTime - last_update) > 100) {
            var diffTime = curTime - last_update;
            last_update = curTime;
            x = acceleration.x;
            y = acceleration.y;
            z = acceleration.z;
            var speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000;

            if (speed > SHAKE_THRESHOLD) {
                // times++;
                handelShakingMotion();
            }
            last_x = x;
            last_y = y;
            last_z = z;
        }
    }

    // 设备有摇一摇动作,则对页面已摇次数进行加1,若已经摇到最大次数numMax,则请求抢红包接口
    function handelShakingMotion() {
        if (shake_status == 2 || shake_status == 0) {
            return false;
        }
        num++;
        // 添加摇一摇的声音
        $('#shakingAudio').trigger('play');
        document.getElementById("numberCount").innerHTML = num;
        // setTimeout(function() {
        // times = 0;
        if (num == numMax) {
            num = 0;
            shake_status = 2;
            // 关闭摇一摇的接口
            window.removeEventListener("devicemotion", deviceMotionHandler);
            // 添加摇到红包的声音
            $('#shakingResult').trigger('play'); 
            // 摇一摇结束之后,请求抢红包接口
            drawRedbag(openid);
        }
        // }, 100); //测试得知80是比较理想的数值
    }

    

    // 发送抢红包请求
    function drawRedbag(openid){
        console.log("drawRedbag");
        var url = globalConfig.pre_api_url + "/wxwall_api/redbag/draw_redbag.php";
        var param = {
            "openid":openid
        };
        request(url,param,function(response){
            // 请求抢红包接口成功
            var redBagData = response.data;
            // $('#shakingResult').trigger('play');
            price = redBagData.price;
            refreshView(current_redbag,true);
            console.log(response.msg);
        });

    }

    // 抢红包进行中,监听摇一摇的动作
    function listenPhoneShake() {
        if (window.DeviceMotionEvent) {
            window.addEventListener('devicemotion', deviceMotionHandler,false);
            console.log("addEventListener devicemotion");
        } else {
            alert('抱歉,你的手机配置实在有些过不去,考虑换个新的再来试试吧');
        }
    }

    // 当前红包:刷新界面
    function refreshView(redbag,is_show_redbag){
        // 显示没有红包
        if( redbag === undefined ){
            $('#shake_view').hide();
            $('#countdown').hide();
            $('#redBagInfo').hide();
            $('#nextRedBagActivity').hide();
            $('#activityEnd').hide();
            $('#redbagRecordPage').hide();
            $('#noRushRedbag').hide();
            $('#noData').show();
            return;
        }
        // 有红包,但都已经无效了
        if (redbag === null) {
            $('#shake_view').hide();
            $('#countdown').hide();
            $('#redBagInfo').hide();
            $('#nextRedBagActivity').hide();
            $('#activityEnd').hide(); 
            $('#noData').hide();
            // 显示红包记录/或者没有抢到红包
            getRedbagRecord();
            // $('#redbagRecordPage').show();
            return;
        }

        var status = redbag.status;
        if (status == '0') {
            //显示倒计时
            $("#shake_view").hide();
            $('#redBagInfo').hide();
            $('#nextRedBagActivity').hide();
            $('#activityEnd').hide();
            $("#countdown").show();    
        }else if (status == '1'){
            if (is_show_redbag == true) {
                $('#hostName').text( activity_title + "的红包" );
                $('#fee').text('成功抢到' + price +'元');
                $('#shake_view').hide();
                $('#nextRedBagActivity').hide();
                $('#activityEnd').hide();
                $("#countdown").hide();  
                $('#redBagInfo').show();
                return;
            }else{
                //显示摇一摇
                $("#countdown").hide(); 
                $('#redBagInfo').hide();
                $('#nextRedBagActivity').hide();
                $('#activityEnd').hide();  
                $('#redBagInfo').hide();
                $("#shake_view").show();
            }
           
        }else if(status == '2'){
            // 判断是否还有下一轮红包,在用户没有抢到红包的情况下, 
            // 有下一轮红包就显示进入下一轮,没有的话就显示活动结束
            // 当用户抢到红包,就不会进入这种情况
            var nextRedbag = getAvailableRedbag();
            if (nextRedbag == null) {
                //若无,显示已经结束;.......
                $('#redBagInfo').hide();
                $("#shake_view").hide(); 
                $("#countdown").hide(); 
                $('#nextRedBagActivity').hide();  
                if( price == 0 ){
                    $('#endActivityPageTxt').text('很可惜,您没抢到红包');
                }else{
                    $('#endActivityPageTxt').text('成功抢到' + price + '元');
                }
                $('#activityEnd').show();
            }else{
                //若有,显示还有下一轮......
                $('#redBagInfo').hide();
                $("#countdown").hide(); 
                $('#activityEnd').hide();
                $("#shake_view").hide();
                if( price == 0 ){
                    $('#promst').text('很可惜,您没抢到红包');
                }else{
                    $('#promst').text('成功抢到' + price + '元');
                }
                $('#nextRedBagActivity').show();
            }
        }
    }

    // 获取当前有效的红包
    function getAvailableRedbag(){
        var length = redbags.length;
        // 没有红包活动返回null
        if (length == 0) {
            return null;
        }
        // 遍历红包列表,取到第一个有效的红包,若有则返回当前有效的红包
        for(var i = 0; i < length; i++){
            var redbag = redbags[i];
            var status = redbag.status;
            // 主要获取到第一个有效的红包就返回当前有效的红包,并且退出该函数
            if (status != '2') {
                return redbag;
                break;
            }
        }
        // 没有有效的红包,即所有的红包活动都结束了
        return null;       
    }

    // 开始摇红包倒计时
    function startCount(startTime) {  
        // var timeContent = $('#timeContent');   //显示倒计时的框
        var endTime = new Date(startTime.replace(/-/g,'/'));     //红包开始的时间
        var countTimer = setInterval(
            function() {
                var nowTime = new Date();
                var time = endTime.getTime() - nowTime.getTime() + time_distance; //截止时间和开始时间相差的毫秒数
                if (!isNaN(time) && time >= 0) {
                    var day = parseInt(time / 1000 / 60 / 60 / 24);
                    var hour = parseInt(time / 1000 / 60 / 60 % 24);
                    var minute = parseInt(time / 1000 / 60 % 60);
                    var second = parseInt(time / 1000 % 60);
                    if (time == 0) {
                        current_redbag.status = "1";
                        refreshView(current_redbag,false);
                    }else if (time <= 10000) {
                        // 调用10秒倒计时动画
                        $('#timeContent').text( second + '秒' );
                    } else if (time <= 120000) {
                        // 倒数120秒的时候
                        var secondLeft = minute * 60 + second;
                        $('#timeContent').text( secondLeft + '秒');
                    } else {
                        $('#timeContent').text( day + '天' + hour + '小时' + minute + '分钟' + second + '秒');
                    }
                } else if (time < 0) {
                    clearInterval(countTimer);
                }
            }, 1000
        );
    }

    // 检查红包状态变化的长轮询
    function check_redbag_status(redBagId,oldStatus,timeOut,startTime) {
        var url = globalConfig.pre_api_url + "/wxwall_api/redbag/check_redbag_status.php"; //检查红包状态的url
        var redbag_id = redBagId;
        var old_status = oldStatus;
        var time_out = timeOut;
        var start_time = startTime;
        var param = {
            "redbag_id": redbag_id,
            "old_status": old_status,
            "time_out": time_out
        };
        $.ajax({
            // 提交数据的类型
            type: "POST",
            // 提交的网址
            url: url,
            // 提交的数据
            data: param,
            // 返回数据的格式
            datatype: "json",
            // 在请求之前调用的函数
            beforeSend: function() {

            },
            // 成功返回之后调用的函数
            success: function(response) {
                response = eval("(" + response + ")");
                var status = response.status;
                if (status == '2') {
                    current_redbag.status = response.data.new_status;//很重要
                    handleRedbag(current_redbag); 
                    if (current_redbag.status == '2') {
                        return;
                    }
               }
                check_redbag_status(redbag_id,current_redbag.status,time_out,start_time);
                // console.log(response.msg);
            },
            // 执行后调用的函数
            complete: function(XMLHttpRequest, textStatus) {
                // console.log(textStatus);
            },
            // 调用出错执行的函数
            error: function() {
                console.log("error");
                setTimeout(function(){
                    check_redbag_status(redbag_id,old_status,time_out,start_time);
                }, 500); //这里是500ms吗??失败后果500ms再次请求
            },
        });
    }

    // 请求红包列表
    function requestRedbags(activity_id){
        var get_redbag_list_url = globalConfig.pre_api_url + "/wxwall_api/redbag/get_redbag_list.php"; //获取红包列表的url
        data = {
            "activity_id": activity_id,
        };
        // 向后台请求红包列表,并根据每个红包的status进行相应的处理
        request(get_redbag_list_url, data, function(response) {
            var datas = response.data;
            redbags = datas.redbags;
            // 当没有红包活动的时候,提示没有红包
            if( datas == '' || response.status == '6'){
                refreshView(undefined,false);
                return;
            }
            // redbag 存储当前有效的红包或者null
            var redbag = getAvailableRedbag();
            // 当有红包活动的时候,但是没有有效红包,显示抢到红包的信息
            if( redbag === null ){
                refreshView(null,false);
                return;
            }
            var servie_time = new Date(datas.current_time.replace(/-/g,'/'));  //卸载下面,防止datas=‘’的时候,replace()函数出错
            var local_time = new Date();
            time_distance = local_time.getTime() - servie_time.getTime();     //服务器和用户的时间相差的毫秒数
            // 获取红包列表
            var length = redbags.length;
            var redbag_id = redbag.id;
            var old_status = redbag.status;
            var start_time = redbag.start_time;
            var time_out = 40; 
            current_redbag = redbag;
            // 处理当前的红包
            handleRedbag(redbag);
            // 长轮询检测status
            check_redbag_status(redbag_id,old_status,time_out,start_time);          

        });      
    }

    // 处理当前有效的红包
    function handleRedbag(redbag){
        var status = redbag.status;
        var start_time = redbag.start_time;
        // 
        refreshView(redbag,false);
        // $("#device_log").append("<li>status:"+status+"<li>");

        if (status == '0') {
            //显示倒计时
            startCount(start_time);
        }else if(status == '1'){
            //监听摇一摇
            if (isTestEnv == true) {
                monitor_shake();
            }else{
                listenPhoneShake();
            }

        }else if(status == '2'){
            // refreshView()函数已经处理了
            //结束该轮抢红包,进入了结束界面

            //关闭用户可以摇红包的能力

            //提示用户是否还有下一轮红包活动,如果有,则引导用户操作;如果没有,提示没有。
        }
    }

   
});


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值