听了一个知乎 Live 的建议,要把项目中学到的东西沉淀下来以备将来面试时有东西可说。因此,我先对 ccoode/timer 这个小项目进行说明。

这个项目是给学习部做的辩论赛倒计时器。原来的版本是用原生 JS 写的,我也用 JS 实现了一个,但是那个实现只精确到秒,而且刚看完 React 官网的教程、捣鼓了 webpack 的我想找个项目练练手(好吧,我目前只有这个项目)。

用户介面上我借鉴了老的计时器,毕竟辩论赛这么严肃的事情,太花哨不太好。我也想弄个更好的介面,可是因为前面那一点,和我的设计能力不足,我不知怎么做。

不考虑介面和各种生成代码的工具,我将简单讲讲实现计时器过程遇到的难点。

起初,计时器逻辑和介面不分离。因为看到 GayHub 上的某位大大实现的计时器实现的“可复用计时器”,再加上最近在看的《Unix 编程艺术》有关策略与逻辑分离的内容,所以我知道了其中的必要。

策略与逻辑分离,提高代码的可维护性。介面与模型之间通过介面传递给模型的回调函数以及模型提供的方法进行通信,这是我自己的理解,不知道对不对。分离出来的模型看起来很简单,start方法开始计时,pause方法暂停计时,_sync方法执行回调函数,用来输出数据……

由于有暂停的功能,如果简单的用秒作为单位计时,连续点击开始暂停,时间很快就过去了,所以应该用毫秒作为单位。解决精确度的关键是确定暂停时所剩余的时间,具体方法:调用 start 时记录 startTimeDate.now() 或者 performance.now() 的值,调用 pause 时,更新 timeout(剩余时间)、left(上一次暂停剩余时间)为 left - (Date.now() - startTime)。除此之外,还要注意 setTimeout 中的时间间隔参数设为 timeout % 1000 || 1000

我写得的这么简单,还不如直接看代码呢。