发现问题到解决问题的经过是这样的。
距离下班还剩一个小时了...
突然来了一个新需求,客户因为场地售卖火爆需要排队抢购,所以客户约定每天早上七点开始预订下一周当天的场地。这就涉及到整点预订的问题,为了优化用户体验,我们约定提前十分钟开始倒计时,让顾客能感受运动产品的动感,也让产品朝着“好玩”进发。
一接到这个需求,这个简单呀,应该可以赶上下班时间,顿时思路如涌泉:
顾客一打开页面,立马请求接口获取场地售卖时间,拿到时间后结合手机时间做比较,是否到了可售卖时间,是否过了可售卖的截至时间;如果未到可售卖时间那是否到了10分钟的倒计时时间。
假设到了倒计时时间,我们开始倒数,到了可售卖时间再次调用接口刷新页面即可实现倒计时抢场地效果。
至此,一顿猛虎操作,开发、上测试,没问题刚好到点,下班走起。
刚走到地铁站,测试发来一条信息:“你这也叫做完了没问题,赶紧给我回来。”
内心一惊,测试过的会有问题,赶紧往回走?
回到公司测试说正常流程是没有问题,但是一旦息屏了一会或者切换到其它应用去了一段时间返回应用,就会出现倒计时不准确问题。这就纳闷了,都是常规代码问题肯定是出现在倒计时上了。细细回想了一下倒计时的机制,倒计时本身是没有问题的,通过事件循环 + 观察者实现,同时切换应用后倒计时页面也不存在CPU被别的I/O占用的情况;诶,不对,js在一个单线程上执行,切换应用一段时间后这个线程虽然没被销毁,但是会不会被挂起来了呢,一但挂起那倒计时肯定是要走不准的了。
这就是问题的关键所在了,不能继续沿用倒计时自减的方案了。脑子灵光一闪,那就每次倒计时都去读取手机时间,这样就能确保倒计时准确无误了。哈哈,聪明。
一顿操作...回家。
上线运行了一天,第二天得到反馈,有的倒计时不准确(快或者慢的都有),有的倒计时结束后场地状态没有刷新。居然还有问题,启动bug分析模式...针对问题一倒计时不准确,倒计时来自于手机事件计算出啦的,那就是手机时间存在误差了;问题二场地状态为更新,有可能是前端倒计时结束,但是后端并未到达临界时间,这时场地状态肯定是不会更新的。针对这两个问题,该怎么解决呢;
哦,手机时间一般来自网络时间,但是手机时间是可以手动更改的,也就是说手机的时间是不可靠的,那时间就必须来自于服务器了。但是倒计时来自于服务器,那是不是每过一秒都要去请求一次服务器接口呢,这显然是不可取的,宁愿时间不准也不能让服务器崩溃了。既要确保到点能刷出新的场地状态(这个时间一定来自于服务器)又要确保第一次的问题不会出现,那只能想办法结合两种时间了。
又一个初步的想法出来了,一打开页面即请求服务器时间,然后通过某种映射让它和手机时间绑定,这样就可以解决这两个问题了。这个映射是什么呢?脑子有点想不清楚了。
那就笔墨伺候。
纸上画着逻辑关系图,一个条件一个条件的罗列出来,咦,好像有那么点感觉了。
倒计时的截止时间是手机当前时间、倒计时剩余时间共同决定的,手机时间好办,倒计时剩余时间 = 到点售卖时间 - 获取的服务器时间。咦,好像问题难点解决了,后面的就是条件判断 + 循环了。
截止,问题好像改完了,基本能满足倒计时结束场地状态会更新也不会出现息屏后倒计时不准确的问题。
又继续想了一下会不会还存在什么隐藏的bug呢,这个需求好像没有看到的这么简单。
后面百度了一下,看到很多类似的文章,大意了大意了。还有服务器的响应时间,setTimeout的精度问题。
这时我脑海里想到了抢茅台和12306抢票。