携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第N天,点击查看活动详情 >>PS:第3天。
请通过Promise,async.await 三者实现简单的信号灯
转换流程:30s、灯3s、灯2s,往复循环在控制台打印即可,不需要实现界面。
不需要我实现界面??? 不!! 我偏要实现!!!
01 来来来!!上代码
html
<ul>
<li class="red"></li>
<li class="green"></li>
<li class="yellow"></li>
<span></span>
</ul>
CSS
<style>
ul {
list-style: none;
width: 400px;
height: 100px;
background-color: #ccc;
display: flex;
margin: 0;
padding: 0;
}
ul li {
width: 80px;
height: 80px;
border-radius: 50%;
margin: 10px;
opacity: 0.2;
}
ul li:nth-child(1) {
background-color: red;
}
ul li:nth-child(2) {
background-color: green;
}
ul li:nth-child(3) {
background-color: yellow;
}
span {
display: inline-block;
width: 100px;
height: 100px;
background-color: #666;
text-align: center;
line-height: 100px;
color: red;
font-size: 60px;
}
.active {
opacity: 1;
}
</style>
JS
<script>
let lis = document.querySelectorAll("li");
let span = document.querySelector("span");
function timer(color, delay) {
let d = delay;
document.querySelector("span").innerHTML = d / 1000;
return new Promise((resolve, reject) => {
let timeId = setInterval(() => {
if (d <= 1000) {
return clearInterval(timeId);
} else {
d -= 1000;
console.log(color, d);
document.querySelector("span").innerHTML = d / 1000;
}
}, 1000);
document.querySelector("." + color).classList.add("active");
let timeId2 = setTimeout(() => {
lis.forEach((item) => {
item.classList.remove("active");
});
resolve();
}, delay);
});
}
async function light() {
await timer("red", 10000);
await timer("green", 5000);
await timer("yellow", 3000);
light();
}
light();
</script>
02 代码剖析
ul li {
width: 80px;
height: 80px;
border-radius: 50%;
margin: 10px;
opacity: 0.2;
}
.active {
opacity: 1;
}
- 红绿灯三个灯的亮暗状态由active控制(因此初始三个灯的透明度opacity调为0.2)
- Active的样式为opacity:1 ,因此控制灯的亮暗,span标签显示当前秒数
let lis = document.querySelectorAll("li");
let span = document.querySelector("span");
function timer(color, delay) {
let d = delay;
document.querySelector("span").innerHTML = d / 1000;
return new Promise((resolve, reject) => {
let timeId = setInterval(() => {
if (d <= 1000) {
return clearInterval(timeId);
} else {
d -= 1000;
console.log(color, d);
document.querySelector("span").innerHTML = d / 1000;
}
}, 1000);
document.querySelector("." + color).classList.add("active");
let timeId2 = setTimeout(() => {
lis.forEach((item) => {
item.classList.remove("active");
});
resolve();
}, delay);
});
}
获取DOM
- 获取dom,
lis伪数组(所有的li标签),span标签 - 创建函数命名为
timer,传参:颜色每个灯总的持续时间 - 声明变量d接收灯持续时间的参数,把span标签的内容改为
灯的总持续时间
间歇定时器
- return 回一个
promise函数,并创建打开间歇定时器setInterval - 在间歇定时器中判定灯亮的总时长是否已小于等于1秒,如果是,则关掉定时器
- 如果不小于1秒,那灯亮的总时长每次定时器运行就减一秒
(-= 1000 ),并设置span标签内的内容,灯亮的总时长除以1000 (要显示的秒数) - 获取当前灯亮颜色的标签,并为其添加
active样式
延时定时器
- 在延时定时器中遍历lis伪数组,删除他们的
active样式 ( 此延时定时器的总时长是灯亮的总时长,因此可以达到当每个灯亮的总时长结束后就删除所有active) - 在延时定时器中调用promise的
resolve(),返回成功的结果
async/await阻塞运行
- 使用async/await调用三次第一次创建的函数,传参 依次为
三个灯的颜色,和总的持续时间。 - 使用递归调用自己,,,最后调用第二次创建的函数
完结!!!撒花!!🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸🌸