You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 23:50:53