
本文共 13550 字,大约阅读时间需要 45 分钟。
长轮询的定义:
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("
发表评论
最新留言
关于作者
