Skip to main content

EventDispatcher

Struct EventDispatcher 

Source
pub struct EventDispatcher { /* private fields */ }
Expand description

事件分发器(对齐 PHP think\Event

对齐 PHP think\Event 类(272 行),提供事件监听/触发/订阅/观察者全 API。

§线程安全

内部用 Arc<RwLock<>> 保护 listenerbind 映射,允许并发读写。 Listener 要求 Send + Sync,可在多线程环境中分发事件。

§PHP 行为对齐

  1. 事件别名(bind)listen('AppInit', ...) 实际注册到 event\AppInit::class
  2. 优先执行(first)listen(event, listener, true)array_unshift 插入队首
  3. 触发返回值trigger 返回所有监听器返回值数组;once=true 返回首个非 null
  4. false 停止:监听器返回 false 时停止后续监听器执行
  5. once 停止once=true 时监听器返回非 null 值停止后续
  6. 点号通配trigger('User.login') 同时触发 User.loginUser.* 监听器
  7. array_uniquetrigger 对监听器列表去重(SORT_REGULAR

Implementations§

Source§

impl EventDispatcher

Source

pub fn new() -> EventDispatcher

创建新的事件分发器(对齐 PHP __construct(App $app),Rust 无需 App 容器)

Source

pub fn listen_events( &self, events: Vec<(String, Vec<Arc<dyn Listener>>)>, ) -> &EventDispatcher

批量注册事件监听(对齐 PHP listenEvents(array $events)

PHP:

Event::listenEvents([
    'UserLogin' => [LoginListener1::class, LoginListener2::class],
    'UserLogout' => [LogoutListener::class],
]);

Rust:

dispatcher.listen_events(vec![
    ("UserLogin".to_string(), vec![Arc::new(LoginListener1), Arc::new(LoginListener2)]),
    ("UserLogout".to_string(), vec![Arc::new(LogoutListener)]),
]);
Source

pub fn listen( &self, event: &str, listener: Arc<dyn Listener>, first: bool, ) -> &EventDispatcher

注册事件监听(对齐 PHP listen(string $event, $listener, bool $first = false)

PHP:

Event::listen('UserLogin', function($params) { ... });
Event::listen('UserLogin', UserLoginListener::class);
Event::listen('UserLogin', [UserLoginListener::class, 'handle'], true); // 优先执行

Rust:

dispatcher.listen("UserLogin", Arc::new(ClosureListener::new(|_| Ok(Value::Null))), false);
dispatcher.listen("UserLogin", Arc::new(UserLoginListener), true); // 优先执行

PHP 行为对齐

  • first=true 时插入队首(array_unshift
  • first=false 时追加队尾($this->listener[$event][]
  • 应用事件别名(bind 映射)
Source

pub fn has_listener(&self, event: &str) -> bool

是否存在事件监听(对齐 PHP hasListener(string $event): bool

Source

pub fn remove(&self, event: &str)

移除事件监听(对齐 PHP remove(string $event): void

Source

pub fn bind(&self, events: Vec<(String, String)>) -> &EventDispatcher

指定事件别名标识(对齐 PHP bind(array $events)

PHP:

Event::bind([
    'UserLogin' => 'app\event\UserLogin',
]);

Rust:

dispatcher.bind(vec![("UserLogin".to_string(), "app\\event\\UserLogin".to_string())]);
Source

pub fn subscribe(&self, subscriber: Arc<dyn Subscriber>) -> &EventDispatcher

注册事件订阅者(对齐 PHP subscribe($subscriber)

PHP:

Event::subscribe(UserEventSubscriber::class);
// 或
Event::subscribe(new UserEventSubscriber());

Rust:

dispatcher.subscribe(Arc::new(UserEventSubscriber));

PHP 行为对齐

  • 若订阅者有 subscribe 方法 → 手动订阅(调用 $subscriber->subscribe($this)
  • 否则 → 智能订阅(调用 observe($subscriber)

Rust 端统一通过 Subscriber trait 的 subscribe 方法手动订阅。 若需智能订阅,用 observe 方法。

Source

pub fn observe( &self, observer: Arc<dyn Observer>, prefix: &str, ) -> &EventDispatcher

自动注册事件观察者(对齐 PHP observe($observer, string $prefix = '')

PHP:

Event::observe(new UserObserver());
// 自动注册 UserObserver 的 onLogin() → 'Login' 事件

Rust:

dispatcher.observe(Arc::new(UserObserver), "");

PHP 行为对齐

  • 反射获取所有 onXxx 公开方法
  • 注册 listen($prefix . $event_name, [$observer, 'on' . $event_name])
  • 若有 eventPrefix 属性,用作前缀

Rust 端通过 Observer trait 的 events() 方法声明事件映射, 避免运行时反射(Rust 无反射)。

Source

pub fn trigger( &self, event: &str, params: &Value, once: bool, ) -> Result<Vec<Value>, EventError>

触发事件(对齐 PHP trigger($event, $params = null, bool $once = false)

PHP:

$results = Event::trigger('UserLogin', ['user_id' => 123]);
$first = Event::trigger('UserLogin', ['user_id' => 123], true); // 只获取一个有效返回值

Rust:

let results = dispatcher.trigger("UserLogin", &json!({"user_id": 123}), false).unwrap();
let first = dispatcher.trigger("UserLogin", &json!({"user_id": 123}), true).unwrap();

PHP 行为对齐

  1. $event 是对象,取类名作为事件名,对象作为参数
  2. 应用事件别名(bind 映射)
  3. 点号通配:User.login 同时触发 User.loginUser.*
  4. array_unique 对监听器去重
  5. 逐个调用 dispatch,返回值收集到 $result
  6. 监听器返回 false → 停止后续
  7. once=true 且监听器返回非 null → 停止后续
  8. once=false 返回所有返回值数组;once=true 返回最后一个非 null 返回值
Source

pub fn trigger_spawn( &self, event: &str, params: &Value, ) -> Vec<JoinHandle<Result<Value, EventError>>>

异步触发事件 — fire-and-forget(Rust 特有扩展,对齐 think-swoole 异步事件分发)

每个监听器在独立的 tokio::task 中并发执行,立即返回 JoinHandle 列表不等待。 适用于非关键事件(日志、指标、通知),不阻塞当前请求。

注意:必须在 tokio 运行时中调用(axum 服务器已提供运行时)。 调用方可选择 .await JoinHandle 获取结果,或丢弃 JoinHandle 实现 fire-and-forget。

与同步 trigger 的差异

  • 同步 trigger:逐个串行执行,支持 once/false 停止
  • 异步 trigger_spawn:并发执行,不支持 once/false 停止(各监听器独立运行)
  • 两者的 bind 别名 / 点号通配 / 去重逻辑完全一致(共用 collect_listeners

Rust:

// fire-and-forget(丢弃 JoinHandle)
dispatcher.trigger_spawn("UserLogin", &json!({"user_id": 123}));

// 等待所有监听器完成
let handles = dispatcher.trigger_spawn("UserLogin", &json!({"user_id": 123}));
for handle in handles {
    let _ = handle.await;
}
Source

pub async fn trigger_async( &self, event: &str, params: &Value, ) -> Vec<Result<Value, EventError>>

异步触发事件并等待所有监听器完成(Rust 特有扩展,对齐 think-swoole 异步事件分发)

等价于 trigger_spawn + 逐个 .await,返回所有监听器的结果列表。 监听器错误被收集到 Vec 中(不传播),包括 task panic 产生的 JoinError

注意:必须在 tokio 运行时中调用。监听器并发执行,结果顺序与注册顺序一致 (因为 trigger_spawn 返回的 JoinHandle 列表保持注册顺序)。

Rust:

let results = dispatcher.trigger_async("UserLogin", &json!({"user_id": 123})).await;
for result in &results {
    if let Err(e) = result {
        eprintln!("Listener error: {}", e);
    }
}
Source

pub fn until( &self, event: &str, params: &Value, ) -> Result<Vec<Value>, EventError>

触发事件(只获取一个有效返回值)(对齐 PHP until($event, $params = null)

等价 trigger(event, params, true),返回最后一个非 null 返回值。

Source

pub fn listener_count(&self, event: &str) -> usize

获取事件的所有监听器数量(PHP 无对应 API,Rust 扩展用于测试)

Trait Implementations§

Source§

impl Default for EventDispatcher

Source§

fn default() -> EventDispatcher

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more