LeetCode 2694 EventEmitter实现中console.log()的异常行为
解决LeetCode 2694题EventEmitter中console.log影响程序行为的问题
问题本质
你代码里用Date.now()作为回调的唯一标识,但Date.now()的精度是毫秒级的。当连续调用subscribe时(没加console.log的情况下,两次调用几乎同时完成),两个回调的timestamp会完全相同。这时候调用sub1.unsubscribe(),过滤条件会把所有timestamp等于该值的回调都删掉——也就是同时干掉了sub1和sub2的回调,所以emit的时候输出空数组。
而加了console.log()之后,它会带来微小的延迟,让两次subscribe的Date.now()生成不同的时间戳,这时候unsubscribe只会删掉sub1的回调,sub2的回调保留,emit自然输出预期的[7]。
修复方案
放弃用时间戳做唯一标识,改用递增的计数器或者UUID来生成唯一ID,这样能保证每个订阅的标识绝对唯一。
修改后的代码
type Callback = (...args: any[]) => any; type Subscription = { unsubscribe: () => void; }; type StampedCallback = { callback: Callback; id: number }; class EventEmitter { events: Record<string, StampedCallback[]> = {}; private nextId = 1; // 用递增计数器生成唯一ID subscribe(eventName: string, callback: Callback): Subscription { if (!this.events[eventName]) this.events[eventName] = []; const currentId = this.nextId++; this.events[eventName].push({ callback, id: currentId }); return { unsubscribe: () => { this.events[eventName] = this.events[eventName].filter( (item) => item.id !== currentId, ); }, }; } emit(eventName: string, args: any[] = []): any[] { return this.events[eventName]?.map(({ callback }) => callback(...args)) ?? []; } }
测试结果
修改后不管有没有console.log(),执行测试代码都会输出Output: [7],完全符合预期。
内容的提问来源于stack exchange,提问作者astatochek
相关产品推荐
相关产品推荐

