frodeborli / gjallarhorn

事件发射器功能,包括 on()、off()、once() 方法,用于订阅事件。

1.0.2 2022-12-03 23:49 UTC

This package is auto-updated.

Last update: 2024-09-04 03:37:02 UTC


README

订阅和发射事件。支持使用 PHP 8 Fibers 的异步事件和同步事件。

用法

EventEmitter 接口和 EventEmitterTrait 用于任何发射事件的类。

事件发射器类

use Gjallarhorn\{
    EventEmitter,
    EventEmitterTrait
};

/**
 * These annotations allow you to provide better type hinting in your IDE. Change the `Event $event` according
 * to your requirements. In this case we're using PHP 8.1 enums (see below for more information).
 * 
 * @method void on(MatchEvent $event, Closure ...$listener) Subscribe to an event
 * @method void off(MatchEvent $event, Closure ...$listener) Unsubscribe from an event
 * @method void once(MatchEvent $event, Closure ...$listener) Subscribe to only the next invocation of this event
 */
class FootballMatch implements EventEmitter {
    use EventEmitterTrait;

    /**
     * This function sends off a synchronous event message. If this
     * event is emitted from inside an asynchronous event listener,
     * then this event will effectively also be asynchronous.
     */
    public function triggerGoalEvent(int $player_number, bool $homeTeam) {
        return $this->trigger(MatchEvent::GOAL, $player_number, $homeTeam);
    }

    /**
     * This function emits the event and returns a Promise object which
     * can be resolved later by calling `$promise->wait()`.
     */
    public function triggerGoalEventAsync(int $player_number, bool $homeTeam) {
        return $thsi->triggerAsync(MatchEvent::GOAL, $player_number, $homeTeam);
    }
}

订阅和取消订阅事件

向事件源对象添加监听器非常简单

/**
 * An event handler
 */
function handle_goal_scores(...$args) {
    // handle the event
}

/**
 * Subscribing to goal scores
 */
$match->on(SomeType::GOAL_SCORED, handle_goal_scores(...));

/**
 * Unsubscribing
 */
$match->off(SomeType::GOAL_SCORED, handle_goal_scores(...));

/**
 * Subscribe only to the next goal
 */
$match->once(SomeType::GOAL_SCORED, function(int $id, DateTimeInterface $time) {
    // The next event
});

异步事件处理器

事件可以异步触发。在这种情况下,EventEmitterTrait::trigger() 函数将返回一个 Promiselike 对象(即任何具有与 function then($onFulfilled, $onRejected) 兼容签名的对象)。

提示 要处理各种承诺类型,您可以考虑使用 RaceTrack\Promise::promisify() 方法。此方法将返回一个具有所有您需要用于处理异步代码的功能的 RaceTrack\Promise 实例。

运行异步事件监听器

<?php
use Gjallarhorn\{
    EventEmitter,
    EventEmitterTrait
};

enum MyEvent: string {
    case GOOD_EVENT = 'GOOD_EVENT';
    case BAD_EVENT = 'BAD_EVENT';
}

/**
 * @method void on(MyEvent $event, Closure ...$listener) Subscribe to an event
 * @method void off(MyEvent $event, Closure ...$listener) Unsubscribe from an event
 * @method void once(MyEvent $event, Closure ...$listener) Subscribe only to the next invocation of the event
 */
class SomeClass implements EventEmitter {
    use EventEmitterTrait;

    public function triggerGoodEvent(): void {
        $promise = $this->triggerAsync(MyEvent::GOOD_EVENT, $this);
        echo "This happens before all events have been resolved\n";
        $results = $promise->await();
    }
}

$instance = new SomeClass();

$instance->on(MyEvent::GOOD_EVENT, function(SomeClass $emitter) {
    // Sleep for 2 seconds while allowing other code to progress
    Fiber::suspend(Promise::sleep(2));
    echo "I've slept for 2 seconds\n";
});

$instance->triggerGoodEvent();