使用事件替代 callback