倒计时:
手机倒计时会有两个问题:
1、返回到倒计时页面时,倒计时不是最新的
2、锁屏后,再打开,倒计时不是最新的
经校验发现,后退时,Jquery的该方法都会执行,因此可解决问题1.
$(function(){
});
第一方案
会有问题:后退更新,锁屏不更新
$(function(){ $.get('/auction/getTimeCountDown.html',{ auctionIds: timeIds.join(","),idd : Math.random()}, function(data) { afterGetNewSeconds(data); } ); });
启动方法中加入getTimeCountDown请求,每次获取最新倒计时秒数
第二版:
正常,没有问题。
进入时取一次剩余倒计时秒数m
请求前纪录客户端时间a,请求后纪录客户端时间b, (b-a)/2 为网络延时
请求后由当前客户端时间,加上返回的剩余倒计时秒数m,再减去网络延时,得到当前客户端的倒计时结束时间
客户端JS定时器,10秒刷新一次,获取到当前时间与客户端结束时间的秒数差c,刷新倒计时
若定时器倒计时的秒数(1秒刷一次,10秒后的秒数)与 c 误差在1秒内,不刷新定时器,否则清除老定时器,生成新定时器
具体代码如下:
HTML:
倒计时:<i class="auctTime" id="<@getStringValue cdo=cdoAuction col='nAuctionId' />"></i>
timer.js:
var finishArray = []; var timerArray = []; //处理网络延时时间 var startTime ; var endTime ; //保存歌倒计时定时器,清除定时器时使用 var map = new HashMap(); //保存本地倒计时中的最新秒数,与10秒刷新获取的本地客户端结束时间倒计时比较 var map2 = new HashMap(); var obj = new Object(); $(function(){ //获取需倒计时的兑换产品Id var timeIds = []; $(".auctTime").each(function(){ var id = $(this).attr("id"); timeIds[timeIds.length] = id; }) if(timeIds.length == 0) return; startTime = new Date(); //获取最新时间 $.get('/auction/getTimeCountDown.html',{ auctionIds: timeIds.join(","),idd : Math.random()}, function(data) { afterGetNewSeconds(data); } ); window.setInterval(refreshCountDown,10000); }); function timer(intDiff,id){ var intervalname = "interval"+id; var timerVar = window.setInterval(function(){ var day=0, hour=0, minute=0, second=0;//时间默认值 if(intDiff > 0){ day = Math.floor(intDiff / (60 * 60 * 24)); hour = Math.floor(intDiff / (60 * 60)) - (day * 24); minute = Math.floor(intDiff / 60) - (day * 24 * 60) - (hour * 60); second = Math.floor(intDiff) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60); } hour = day * 24 + hour; if (hour <= 9) hour = '0' + hour; if (minute <= 9) minute = '0' + minute; if (second <= 9) second = '0' + second; var str = ""; str += hour + ":"; str += minute + ":"; str += second; intDiff--; console.log("======================="); map2.put(intervalname,intDiff); $("#" + id).html(str); if(intDiff <= 0){ if(typeof isdetail != "undefined" && isdetail == "1"){ //刷新当前页面 location.reload(); }else{ $("#bidding_"+id).remove(); $(".cd_"+id).hide(); $("#btn_"+id).text("竞拍结束"); clearInterval(timerVar); } } }, 1000); map.put(intervalname,timerVar); timerArray[timerArray.length] = timerVar; } //获取客户端当前时间与 客户端结束时间作比较,刷新倒计时 function refreshCountDown(){ if(finishArray.length >= 0){ for(var i in finishArray){ refreshPerCountDown(finishArray[i]); } } } function afterGetNewSeconds(data){ endTime = new Date(); var interval = endTime.getTime() - startTime.getTime(); data = eval('(' + data + ')'); if(data.code == 0){ var result = data.result; if(typeof result == "undefined" || result.length == 0) return; for(var i in result){ var exId = result[i].auctionId; var newSecond = result[i].seconds; var newMiSeconds; if(interval > 0){ //newSecond = newSecond - (interval/1000); newMiSeconds = (newSecond * 1000) - (interval/2); } //计算客户端结束时间 var finishTime = new Date().getTime() + newMiSeconds; var finishTimeStr = exId+"_"+finishTime; finishArray[finishArray.length] = finishTimeStr; refreshPerCountDown(finishTimeStr); } } } var exId,finishTime,seconds; //刷新单个 已保存客户端结束时间的倒计时 function refreshPerCountDown(finishTimeStr){ //clearInterval(intervalVar); var curTime = new Date().getTime(); exId = finishTimeStr.split("_")[0]; finishTime = finishTimeStr.split("_")[1]; seconds = (finishTime - curTime)/1000; refreshTimer(exId,seconds); } //刷新最新倒计时 function refreshTimer(exId,newSecond){ var intervalname = "interval"+exId; var sed = map2.get(intervalname); var diff = parseFloat(sed) - parseFloat(newSecond); if(sed == null || diff >=1){ clearInterval(map.get(intervalname)); timer(newSecond,exId); } }
后台:
/** * 获取最新倒计时 */ public void getTimeCountDown(){ CDO seconds = new CDO(); String auctionIds = request.getParameter("auctionIds"); if(StringUtils.isBlank(auctionIds)){ seconds.setStringValue("code", "-1"); ajaxForAction(response, seconds.toJSON()); return; } cdoRequest.setStringValue(ITransService.SERVICENAME_KEY, "AuctionService"); cdoRequest.setStringValue(ITransService.TRANSNAME_KEY, "getTimeCountDown"); cdoRequest.setStringValue("auctionIds", auctionIds); Return ret = getServiceBus().handleTrans(cdoRequest, cdoResponse); if(ret.getCode() == 0){ if(cdoResponse.exists("cdosExchange")){ CDO[] cdos = cdoResponse.getCDOArrayValue("cdosExchange"); CDO[] cdosExchange = new CDO[cdos.length]; int i = 0; for(CDO cdo : cdos){ String dataString = cdo.getStringValue("ex"); //if(StringUtils.isBlank(dataString)) continue; String exId = dataString.substring(0,dataString.indexOf("-")); String strTime = dataString.substring(dataString.indexOf("-")+1); long nSecond = DateUtil.getSecond(strTime); CDO exchangeCdo = new CDO(); exchangeCdo.setStringValue("auctionId", exId); exchangeCdo.setLongValue("seconds", nSecond); cdosExchange[i] = exchangeCdo; i++; } if(cdosExchange.length >0){ seconds.setCDOArrayValue("result", cdosExchange); } } } seconds.setStringValue("code", "0"); ajaxForAction(response, seconds.toJSON()); }
SQL:
select CONCAT_WS("-",a.nAuctionId,a.dtEndTime) ex from tbauction a where a.nAuctionId in (
。。。
最新版优化:
最后1分钟或几分钟内,出价后,时间就变为1分钟,直到无人出价为止。
参考了西部数码的竞拍,发现以前考虑的太复杂了,哈哈
西部的JS见附件。
注意的点:
出价成功或失败时,提示使用的不是alert弹窗,而是用的jbox。
alert弹窗出现时,若一直不点,则定时器也会暂停,点击后才继续接着执行,这样如果各客户端点击快慢不同,就会导致各客户端最后的倒计时时间不同。而Jbox则不会阻塞JS,使用jbox.tip也更人性化。
参考:
当有非常多的setTimeout和setInterval时,哪种用法效率高?
======================================================================
1、setInterval计时器不准的问题(setInterval回调堆积): 在js中如果打算使用setInterval进行倒数,计时等功能,往往是不准确的,因为setInterval的回调函数并不是到时后立即执行,而是等系统计算资源空闲下来后才会执行.而下一次触发时间则是在setInterval回调函数执行完毕之后才开始计时,所以如果setInterval内执行的计算过于耗时,或者有其他耗时任务在执行,setInterval的计时会越来越不准,延迟很厉害.
2、setTimeout基于JavaScript运行时内部的事件队列
jQuery源码里很多地方都用到了setTimeout(callback)可以去看看。打个比方:
function read_data(){
read_file();
write_log();
//setTimeout(write_log,0);
}
read_data();
show_data();
假设write_log()花费1秒,那么read_data()得多等1秒才能返回,然后show_data()才能把数据展示给用户。但是用户根本不关心你的日志,让用户为此多等1秒其实毫无意义,这种场景就可以用setTimeout(callback,0)来调用write_log,让read_data()立刻返回并将数据展示给用户。node里可以用nextTick,会更快一些。
伪异步:
【斩草除根】重新认识所谓的“异步”
我们知道,js是单线程执行的。事实上setTimeout和setInterval只是简简单单地通过插入代码到代码队列来实现代码的延迟执行(或者说异步执行)。但是事实上所谓的异步只是一个假象——它同样运行在一个线程上!
那么问题就来了,要是在插入点前的代码执行时间超过了传入setTimeout或setInterval的设定时间会怎样呢?让我们来看看这段代码:
function fn() { setTimeout(function(){alert('can you see me?');},1000); while(true) {} }
你觉得这段代码的执行结果是什么呢?答案是,alert永远不会出现。
这是为什么呢?因为,while这段代码没有执行完,插入在后面的代码便永远不会执行。
综上所述,其实JS终归是单线程产物。无论如何“异步”都不可能突破单线程这个障碍。所以许多的“异步调用”(包括Ajax)事实上也只是“伪异步”而已。只要理解了这么一个概念,也许理解setTimeout和setInterval也就不难了。
=============================================================================
概要代码:
var leftsecond=0; var timerobj = null ; $(function(){ //获取需倒计时的兑换产品Id var timeIds = []; $(".auctTime").each(function(){ var id = $(this).attr("id"); timeIds[timeIds.length] = id; }) if(timeIds.length == 0) return; startTime = new Date(); //获取最新时间 $.get('/auction/getTimeCountDown.html',{ auctionIds: timeIds.join(","),idd : Math.random()}, function(data) { afterGetNewSeconds(data); } ); if(state == "2"){ daojishi(); } //window.setInterval(refreshCountDown,10000); }); /////////////////////////////////////////////////////////////// function timespan(intDiff){ console.log("intDiff::::::" + intDiff); //if(intDiff <= 0) return; var day=0, hour=0, minute=0, second=0;//时间默认值 if(intDiff > 0){ day = Math.floor(intDiff / (60 * 60 * 24)); hour = Math.floor(intDiff / (60 * 60)) - (day * 24); minute = Math.floor(intDiff / 60) - (day * 24 * 60) - (hour * 60); second = Math.floor(intDiff) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60); } hour = day * 24 + hour; if (hour <= 9) hour = '0' + hour; if (minute <= 9) minute = '0' + minute; if (second <= 9) second = '0' + second; var str = ""; str += hour + ":"; str += minute + ":"; str += second; console.log("str:" + str); return str; } function daojishi(){ var time = timespan(leftsecond--); $("#" + auctionId).text( time ); clearTimeout(timerobj); timerobj = setTimeout("daojishi()",1000) } function afterGetNewSeconds(data){ endTime = new Date(); var interval = endTime.getTime() - startTime.getTime(); data = eval('(' + data + ')'); //console.log("data================="); if(data.code == 0){ //console.log("data2================="); var result = data.result; if(typeof result == "undefined" || result.length == 0) return; //console.log("data3================="); for(var i in result){ var exId = result[i].auctionId; var newSecond = result[i].seconds; if(parseInt(auctionId) - parseInt(exId) == 0){ if( Math.abs(newSecond-leftsecond)>=3 ){ leftsecond = parseInt(newSecond) - 1; //正负10的情况下才去改变这个数字// 减1是因为网页上timer要延迟一秒 //console.log("leftsecond=================" + leftsecond); } } } } } function refreshDetailTime(autId,seconds){ console.log("seconds :" + seconds + ",leftsecond:" + leftsecond); if( Math.abs(seconds-leftsecond)>=3 ){ console.log("refreshDetailTime33====" + leftsecond); leftsecond = parseInt(seconds) - 1; //正负10的情况下才去改变这个数字// 减1是因为网页上timer要延迟一秒 console.log("refreshDetailTime44 leftsecond====" + leftsecond); } }
refreshDetailTime 方法为刷出价时,同时刷回来最新的剩余倒计时秒数。
相关推荐
元旦倒计时代码+可设置时间+自动计时 元旦倒计时代码+可设置时间+自动计时 元旦倒计时代码+可设置时间+自动计时 元旦倒计时代码+可设置时间+自动计时 元旦倒计时代码+可设置时间+自动计时 元旦倒计时代码+可设置时间...
倒计时进度条+翻页效果
在PPT演示文稿中,有时我们需要添加倒计时功能,以便在演讲、培训或比赛中把握时间。"PPT倒计时插件+如何在PPT2007内加载宏"是一个专为此目的设计的工具,由作者沈兵于2009年12月17日发布。这个加载宏能够方便用户在...
小程序源码 电商-拼团 倒计时 (代码+截图)小程序源码 电商-拼团 倒计时 (代码+截图)小程序源码 电商-拼团 倒计时 (代码+截图)小程序源码 电商-拼团 倒计时 (代码+截图)小程序源码 电商-拼团 倒计时 (代码+截图)小...
小程序源码 辩论倒计时 (代码+截图)小程序源码 辩论倒计时 (代码+截图)小程序源码 辩论倒计时 (代码+截图)小程序源码 辩论倒计时 (代码+截图)小程序源码 辩论倒计时 (代码+截图)小程序源码 辩论倒计时 (代码+截图)小...
标题中的“倒计时器+定时关机+温馨提示”揭示了这个软件或程序的主要功能,它包括三个核心部分:倒计时器、定时关机和温馨提醒。这是一款小巧但功能丰富的工具,适用于那些需要时间管理或者自动化电脑操作的用户。 ...
【标题】:“元旦倒计时代码+HTML+JavaScript”是一个基于HTML、CSS和JavaScript实现的网页应用,用于显示距离下一个元旦的倒计时。这个应用能够帮助用户追踪时间,为庆祝活动做准备。 【HTML】:HTML(HyperText ...
JavaScript倒计时是一种常见的网页动态效果,用于显示距离某个特定时间点还有多少天、小时、分钟和秒。在本文中,我们将深入探讨如何使用JavaScript实现一个功能完整的倒计时功能,包括从服务器获取结束时间以及实时...
在Android应用开发中,"商品秒杀倒计时功能+ViewPager实现画廊效果"是常见的电商应用中的两个重要特性。这两个功能的结合可以为用户提供更丰富的互动体验,增强购物的吸引力。 首先,我们来深入理解商品秒杀倒计时...
微信小程序——电商-拼团 倒计时(截图+源码).zip 微信小程序——电商-拼团 倒计时(截图+源码).zip 微信小程序——电商-拼团 倒计时(截图+源码).zip 微信小程序——电商-拼团 倒计时(截图+源码).zip 微信小...
日期计算、倒计时以及天数计算是编程领域中常见的功能需求,特别是在日历应用、项目管理、事件提醒等场景中。以下将详细介绍这些概念及其在实际应用中的实现方法。 日期计算涉及到对日期的加减操作,比如计算两个...
一个简单的倒计时程序。 谁说用图形化编程的一定是垃圾?只要用得好,做出好作品不是吹。 不喜勿喷。 一个简单的倒计时程序。 谁说用图形化编程的一定是垃圾?只要用得好,做出好作品不是吹。 不喜勿喷。 一个简单的...
本资源包含的是一个易语言编写的倒计时软件的完整源码、软件成品以及配套的皮肤模块,非常适合初学者学习和研究。 首先,我们来详细探讨易语言倒计时源码的核心知识点: 1. **倒计时功能**:倒计时是程序设计中...
前端语言(HTML+css+JavaScript + canvas)写的一个 2023 年跨年倒计时代码 倒计时日期格式:月-日-时-分-秒 也可以自定义日期格式 自定义添加祝福语等 代码时按照元旦作为计算日期 也可以按照农历新年作为日期格式
微信小程序——辩论倒计时(截图+源码).zip 微信小程序——辩论倒计时(截图+源码).zip 微信小程序——辩论倒计时(截图+源码).zip 微信小程序——辩论倒计时(截图+源码).zip 微信小程序——辩论倒计时(截图+...
通过html+css+javascript写的一个倒计时页面,通过输入分钟和秒数能够倒计时,通过if来判断输入的值得正确性
本项目以Verilog为工具,设计并实现了具有自动计时、手动校时、倒计时、闹钟以及整点报时功能的数字钟,并通过LCD显示器进行直观展示。该设计充分利用了Cyclone II FPGA的性能,实现了高度集成和灵活可配置的数字...
无论是招聘网站、商品秒杀还是新年倒计时等,展示网页倒计时的需求都很常见,本示例代码可以帮助开发人员快速实现和调整倒计时效果,从而提高用户体验和网站吸引力。 该代码的使用场景比较灵活,可以在电商、招聘、...
可以结合`Task.Delay`来实现异步倒计时,避免阻塞线程。 总之,C#的多线程计时器和倒计时功能是构建高效、实时应用程序的重要组成部分。通过理解这些概念和实践,开发者可以更好地控制程序的执行流程,实现复杂的...