const serial = ['Red', 'Yellow', 'Green']
/**
* 延迟指定时间后返回一个Promise对象
*
* @param {number} time - 延迟的时间,以毫秒为单位,默认为1000ms
* @returns {Promise} 返回一个Promise对象
*/
function delay(time = 1000) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, time)
})
}
class Singal {
//获取下一个信号灯颜色
get next() {
return serial[(serial.indexOf(this.sig) + 1) % serial.length];
}
//剩余时间
get remain() {
let diff = this.end - Date.now();
if (diff < 0) {
diff = 0;
}
return diff / 1000;
}
//构造函数
constructor(options) {
this.sig = options.init;
this.times = options.times;
this.eventMap = new Map();
this.eventMap.set('change', new Set())
this.eventMap.set('tick', new Set())
this.setTime()
this.exchange()
}
// 注册事件
on(event, handler) {
this.eventMap.get(event).add(handler);
}
// 取消注册事件
off(event, handler) {
this.eventMap.get(event).delete(handler);
}
// 触发事件
emit(event) {
this.eventMap.get(event).forEach(h => h.call(this, this));
}
//交换信号灯颜色
async exchange() {
await 1;
if (this.remain > 0) {
//不需要切换
this.emit('tick');
await delay(1000)
} else {
this.sig = this.next;
this.setTime();
this.emit('change');
}
//递归调用
this.exchange();
}
//设置时间
setTime() {
//获取开始时间
this.start = Date.now();
//获取等待时间
const time = this.times[serial.indexOf(this.sig)]
//设置结束时间
this.end = this.start + time * 1000;
}
}
const s = new Singal({
init: 'Red',
times: [10, 3, 5]
});
s.on('tick', (e) => {
console.log(e.sig, Math.round(e.remain));
})
/***
* new Map()
* Map是ES6中的一种数据结构,它允许您将键值对存储在一个可迭代的集合中。与JavaScript中的其他对
象(例如对象字面量)相比,Map提供了更灵活的键和更容易使用的API。
以下是创建和使用Map对象的示例:
// 创建一个空的Map对象
var myMap = new Map();
// 添加键值对到Map中
myMap.set('key1', 'value1');
myMap.set('key2', 'value2');
myMap.set('key3', 'value3');
// 从Map中获取值
console.log(myMap.get('key1')); // 输出 "value1"
// 检查Map中是否包含指定的键
console.log(myMap.has('key2')); // 输出 true
// 删除指定的键值对
myMap.delete('key3');
// 遍历Map中的所有键值对
for (var [key, value] of myMap) {
console.log(key + ' = ' + value);
}
在上述代码中,我们首先创建一个空的Map对象,然后使用set()方法向其中添加三个键值对。接着,我们使
用get()方法获取一个指定键对应的值,并使用has()方法检查指定键是否存在于Map中。然后,我们使用
delete()方法删除一个键值对,并使用for...of循环遍历Map中的所有键值对。
需要注意的是,在使用Map时,键可以是任何类型的值,包括字符串、数字、对象等。此外,Map对象是有序
的,即键值对的顺序与它们添加到Map中的顺序相同。
*/
/***
* new Set()
* Set是ES6中的一种数据结构,它允许您存储唯一的值(无重复)。Set类似于数组,但是它们的主要区别
在于Set中的值不能重复,而数组可以包含重复的元素。
* 以下是创建和使用Set对象的示例:
// 创建一个空的Set对象
var mySet = new Set();
// 添加元素到Set中
mySet.add('value1');
mySet.add('value2');
mySet.add('value3');
// 检查Set中是否包含指定的值
console.log(mySet.has('value2')); // 输出 true
// 从Set中删除指定的值
mySet.delete('value3');
// 获取Set中的元素数量
console.log(mySet.size); // 输出 2
// 遍历Set中的所有元素
mySet.forEach(function(value) {
console.log(value);
});
在上述代码中,我们首先创建一个空的Set对象,然后使用add()方法将三个值添加到Set中。接着,我们使
用has()方法检查指定的值是否存在于Set中,并使用delete()方法删除一个值。还可以使用size属性获取
Set中的元素数量。最后,我们使用forEach()方法遍历Set中的所有元素。
需要注意的是,Set中的值可以是任何类型的值,包括基本类型和对象。Set对象中的元素是按照它们被添加
到Set中的顺序进行迭代。另外,Set自动处理值的唯一性,即不会添加重复的值。
*/
/***
在上述代码中,this.exchange()函数被设置为每隔1秒调用一次。在每次调用this.exchange()函数时,
会通过this.emit('tick')触发tick事件。因此,如果要在接收到tick事件时执行相应的回调函数,必须在
代码中调用on('tick', callback)来注册tick事件的回调函数。这样,当tick事件被触发时,就会执行注
册的回调函数。如果没有调用on('tick', callback)来注册tick事件的回调函数,那么就无法在接收到
tick事件时执行相应的操作。
* */
前端简单的红绿灯实现 JS
最新推荐文章于 2024-05-24 23:45:01 发布