【面试题】纯js模拟实现交通信号灯,红灯、黄灯、绿灯循环

1,269 阅读1分钟

前言

前几天去面试,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>