前言
前几天去面试,hr让我现场在vscode用纯js写俩道题,一道是实现lodash的get方法,一道是模拟实现信号灯交替,本篇就信号灯来讲一下。
本人比较菜,当时是写了个Promise配合await实现的,后来在网上百度,发现大部分人都是和我当时做题一样,通过Promise配合async await或者.then来实现的。
回去后就和我哥(java)讲了下,我觉得我的实现方式可能繁琐复杂,不太好,然后给我哥复现了下我当时写的代码,我哥说要是他是面试官看着我的代码那么多行,看都不想看,直接pass,然后给我说你等下看我写,看我用不用的了十行,然后当时他就写了他的实现方法,真的没超过十行= =
我本篇就讲下如何不通过promise,使用递归+延时器实现个完整的信号灯效果。
原题
// 用js模拟写一个交通信号灯,红灯亮5秒后变成绿灯 绿灯亮2秒后变成黄灯 黄灯亮5秒后变成红灯
// 数据是后端给的 不能写死
const arr = [
{ color: 'red', duration: 5000 },
{ color: 'yellow', duration: 2000 },
{ color: 'green', duration: 5000 },
];
实现方式
先放一下我当时做题的Promise+await的实现方式
function changeColor(color, delay) {
return new Promise(res => {
console.log(`${color}要亮${delay / 1000}秒`);
setTimeout(() => {
res();
}, delay);
});
}
async function start() {
for (const item of arr) {
await changeColor(item.color, item.duration);
}
start();
}
start();
再放一下我哥的实现思路
let count = 0;
function fn() {
// 对数组的长度取余 获取当前要亮的灯的下标
let index = count % arr.length;
console.log(`${arr[index].color}要亮${arr[index].duration / 1000}秒`);
setTimeout(() => {
count++;
fn();
}, arr[index].duration);
}
fn(); // 调用fn
包含html完整代码
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.warp {
width: 50px;
height: 200px;
background-color: black;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
border-radius: 20px;
}
.warp .light {
width: 30px;
height: 30px;
background-color: gray;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="warp">
<div class="light"></div>
<div class="light"></div>
<div class="light"></div>
</div>
</body>
<script>
const arr = [
{ color: 'red', duration: 5000 },
{ color: 'yellow', duration: 2000 },
{ color: 'green', duration: 5000 },
];
const lights = document.querySelectorAll('.warp .light');
let count = 0; // 先声明count计数
function fn() {
// 对数组的长度取余 获取当前要亮的灯的下标
let index = count % arr.length;
// 先把所有灯的颜色都还原成灰色
for (const item of lights) {
item.style.backgroundColor = 'gray';
}
// 把当前灯的颜色换成指定颜色
lights[index].style.backgroundColor = arr[index].color;
console.log(`${arr[index].color}要亮${arr[index].duration / 1000}秒`);
setTimeout(() => {
// 每次切换灯光count+1
count++;
// 亮灯n秒后递归 切换其他颜色
fn();
}, arr[index].duration);
}
fn();
</script>
</html>