AI 模型在 2022 年刚问世的时候很多人对此抱有疑问,事实上在开发人员的使用过程中发现,还难堪大用,借助 AI 编程,结果给出的代码自带 bug,我自己写的 bug 还没有修完呢,怎么可能有时间来帮 AI 修 bug?要是你对它给出的答案不满意,多问几遍,甚至它自己都连连抱歉,自顾自的不断给出不一样的答案😂
那时隔 2 年,现在的 AI 模型现在表现的怎么样了,它是否真的能提高我们的开发效率?
下面来看个例子,一探究竟!
数字时钟
数字时钟想必很多人都做过。
不就是简单的显示日期和时间吗?setInterval
一把梭哈!
<template>
<span class="digital-clock">{{ currentDate }}</span>
</template>
<script>
import dayjs from 'dayjs'
export default {
name: 'Clock',
data() {
return {
dayType: [
'星期日',
'星期一',
'星期二',
'星期三',
'星期四',
'星期五',
'星期六'
],
currentDate: '',
}
},
methods: {
getTime() {
this.currentDate = dayjs().format('YYYY-MM-DD HH:mm:ss') + ' ' + this.dayType[(new Date()).getDay()]
},
},
mounted() {
setInterval(() => {
this.getTime()
}, 1000)
},
}
</script>
<style>
.digital-clock {
display: flex;
align-items: center;
color: #83a9e5;
font-size: 14px;
vertical-align: middle;
}
</style>
效果:
等等先别着急,来看看 AI 写的。
<template>
<span class="digital-clock">
<span class="date">{{ date }}</span>
<span class="digit">{{ hours }}</span>
<span class="colon">:</span>
<span class="digit">{{ minutes }}</span>
<span class="colon">:</span>
<span class="digit">{{ seconds }}</span>
</span>
</template>
<script>
import dayjs from 'dayjs'
export default {
name: 'Clock',
data() {
return {
date: '',
hours: '',
minutes: '',
seconds: '',
currentTime: '',
prevTime: '',
myReq: 0,
dayType: [
'星期日',
'星期一',
'星期二',
'星期三',
'星期四',
'星期五',
'星期六'
],
}
},
methods: {
getDate () {
this.date = dayjs().format('yyyy-MM-dd') + ' ' + this.dayType[(new Date()).getDay()]
},
updateTime() {
const date = new Date()
const h = this.padZero(date.getHours())
const m = this.padZero(date.getMinutes())
const s = this.padZero(date.getSeconds())
this.hours = h
this.minutes = m
this.seconds = s
this.currentTime = `${h}:${m}:${s}`
},
padZero(value) {
return value < 10 ? `0${value}` : value
},
updateClock() {
const currentTime = performance.now()
const deltaTime = currentTime - this.prevTime
if (deltaTime >= 1000) {
this.updateTime()
this.prevTime = currentTime
}
this.myReq = requestAnimationFrame(this.updateClock)
}
},
mounted() {
this.getDate()
this.prevTime = performance.now()
this.updateClock()
},
beforeDestroy() {
cancelAnimationFrame(this.myReq)
}
}
</script>
<style scoped lang="scss">
.digital-clock {
display: flex;
align-items: center;
color: #83A9E5;
font-size: 14px;
vertical-align: middle;
}
.digital-clock .date {
margin-right: 4px;
}
.digital-clock .digit {
display: inline-block;
width: 1.2em;
}
.digital-clock .colon {
display: inline-block;
width: 0.4em;
}
</style>
写的蛮好的嘞😳
效果:
分析一下
好家伙,没有直接用 setInterval
,而是用了performance.now()
和 requestAnimationFrame
来替代,通过精确的时间计算来达到每秒更新一次,确保时间更新的准确性和性能最佳。
setInterval 的问题
为什么setInterval
性能差呢?主要有以下几点:
- 时间精度不可靠
setInterval
定时器的执行间隔并不一定是准确的。例如,setInterval(fn, 1000)
表示每隔 1000
毫秒执行一次 fn,但由于 JavaScript 是单线程运行的,其他任务(如页面渲染、大量的 DOM 操作、事件处理)可能会阻塞主线程,导致定时器的执行时间被延迟,无法保持精确的间隔。这种不精确性在处理时间敏感的任务时表现得尤为明显。
- 主线程阻塞
setInterval
运行在主线程上,如果主线程被其他操作(如繁重的计算、DOM 操作)阻塞,定时器的回调函数可能会延迟执行。这种延迟会积累,最终导致定时器的执行与预期不同,甚至出现多个回调函数在阻塞解除后“扎堆”执行的情况,从而导致性能下降。
- 缺乏协调性
setInterval
不会检查先前的回调是否已完成。因此,如果一个定时任务比设定的间隔时间运行得更长,新的定时器回调函数会在旧的回调执行完之前被触发,可能导致内存泄漏或其他意外行为。
- 浏览器节流和后台模式影响
现代浏览器对 setInterval
有节流机制,尤其是在页面切换到后台时,定时器的精度可能大幅降低。比如,Chrome 浏览器会降低后台页面的 setInterval 执行频率以节省资源,这会进一步影响时间任务的准确性。
- 性能劣化与垃圾回收
定时器创建和销毁的频率高且不受控,可能会导致垃圾回收频繁运行,进一步降低性能。
requestAnimationFrame 和 performance 的优势
前面说了,这两个确保了时间更新的准确性和性能最佳,通过对比上次更新时间
和当前时间
来确定是否需要更新显示的时间
,从而实现每秒更新一次。
使用 performance.now()
可以获取高精度的时间戳,而不是依赖 JavaScript 的 Date 对象的低精度时间更新。
而 requestAnimationFrame
更加适合做高频率的任务调度,主要原因如下:
- 与浏览器刷新同步
requestAnimationFrame 会自动将回调函数的执行时间安排在下一次浏览器重绘之前,这意味着它的执行频率与屏幕的刷新率保持同步(通常为每秒 60 次),从而避免了不必要的额外渲染和计算。相比之下,setInterval 会尝试按照设定的时间间隔执行,但不会考虑屏幕刷新节奏,这可能导致丢帧和卡顿。
- 节省 CPU 资源
requestAnimationFrame 在后台标签页或非活动状态时会暂停执行回调函数,节省了 CPU 资源。而 setInterval 即使在后台标签页也会尝试执行,浪费了系统资源。requestAnimationFrame 的这一特性特别适用于需要节约电量或优化资源的场景。
- 防止页面卡顿
在高频率任务调度中,requestAnimationFrame 通过与浏览器的绘制流程协同工作,可以避免多个回调函数扎堆执行的情况。这种协调性降低了页面卡顿的风险,因为浏览器可以更好地控制和优化任务的执行时机。
- 精确控制动画帧率
requestAnimationFrame 让开发者能够精确地控制动画的帧率,使动画和其他高频任务更加流畅、自然。而 setInterval 的时间间隔是基于设置的毫秒数,且可能被其他任务阻塞,导致帧率不稳定或帧丢失。
- 减少不必要的绘制
当页面未处于可见状态或动画不可见时,requestAnimationFrame 会自动停止回调,这样可以有效减少不必要的绘制操作,避免浪费性能。
总的来说它优势在于与浏览器的渲染周期高度协调,使得它成为高频率、帧同步任务(如动画)的最佳选择。它不仅能确保任务以最佳的时间执行,还能优化性能、减少资源消耗,是现代前端动画和实时任务调度的理想工具。
最后还很贴心的做了防止数字变化时带来的文字抖动问题
完了,AI 要代替了我了
看完这个例子,你是不是有点慌张了,短短2年时间,AI已经可以代替程序员写代码了嘛,写的代码还更好了。
别急,事实上,AI 写的那段代码是经过多次修改,反复调教的结果,一开始它也是用 setInterval
来实现的数字时钟(hhhhhhh)。
经过不断的提示:要注意性能、要用 requestAnimationFrame、要考虑时间更新的精确度、试试 performance、时间变化会抖动,要解决等等
在编写过程中,反复调试,AI 才能得出我们满意的答案,这意味着是我们自己首先知道这些知识点,才去提示 AI 让它不断完善代码。
善用 AI
而实际上,善用 AI 确实能帮助我们提高开发效率,比如开发一些简单的组件、给 js 代码加上 ts 类型声明、数据格式转换等等事情,AI 做起来确实很快,省了很多时间。
还有目前比较完善的 AI 辅助编程,基本可以做到想你所想,提高开发效率。
AI 辅助编程工具:
- 豆包MarsCode - 编程助手
- github copilot
- 通义千问
- CodeGeeX
总的来说,我们是来做事情的,能又快又好的完成应该是我们的追求,快点做完不就能摸鱼了嘛;至于说 AI 取代程序员,可以换个角度看待,开发者的角色会慢慢的从单纯的编码者,转向问题解决者、设计者,让 AI 去做那些繁琐的编码任务,我们更关注架构设计、用户体验和创新点;对于新鲜事物,大可不必着急排斥,不如先试试~