事件服务

Noba 的事件服务目前还比较简单,只有一些简单的事件订阅和发布功能。一次完整的事件驱动分为这三步:首先需要创建事件;然后订阅该事件;在事件发生时通知订阅者

创建事件

要创建事件需要先通过 ioc 创建事件服务,然后通过该服务创建包含事件的 Hub

  1. 创建事件服务:
    # main.py
    
    from noba import core
    
    if __name__ == '__main__':
        event = core.make('event')
    
  2. 创建事件:
    事件被包裹在 Hub 中的,一个 Hub 可以有多个事件。该 Hub 可以是一个命名 Hub,命名的目的是方便管理 Hub,但这并不是强制的。创建命名 Hub 的方法有两个(见代码中方法一和方法二)
    # main.py
    
    from noba import core
    
    if __name__ == '__main__':
        event_service = core.make('event')
    
        # 创建一个命名为 'cross over' 的 Hub 方法一。该 hub 包含两个事件:'cross close price', 'cross open  price'
        cross_over_hub = event_service.hub(['cross close price', 'cross open  price'], "cross over")    
    
        # 创建一个命名为 'cross over' 的 Hub 方法二。该 hub 包含两个事件:'cross close price', 'cross open  price'
        cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")
    
  3. 关于 Hub 的一些操作:
    • 通过事件服务获取所有 Hub

      # main.py
      
      from noba import core
      
      if __name__ == '__main__':
          event_service = core.make('event')
          cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")
      
          all_hub = event_service.get_all_hub()
      
    • 事件服务通过名字获取某个 Hub

      # main.py
      
      from noba import core
      
      if __name__ == '__main__':
          event_service = core.make('event')
          cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")
      
          hub = event_service.get_hub('cross over')
          print(cross_over_hub == hub) # True
      
    • 获取 Hub 的所有事件

      # main.py
      
      from noba import core
      
      if __name__ == '__main__':
          event_service = core.make('event')
          cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")
      
          cross_over_hub_event = cross_over_hub.get_events() 
          print(cross_over_hub_event) # ['cross close price', 'cross open  price']
      
    • 获取 Hub 名字

      # main.py
      
      from noba import core
      
      if __name__ == '__main__':
          event_service = core.make('event')
          cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")
          hub_name = cross_over_hub.get_name()
          print(hub_name) # cross over
      
    • 从事件服务中删除 Hub 有两种方式。在 Hub 调用 drop_me 方法;或则调用事件服务的drop方法

      # main.py
      
      from noba import core
      if __name__ == '__main__':
          event_service = core.make('event')
          cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")            
      
          # 方法一
          cross_over_hub.drop_me()
          
          # 方法二
          event_service.drop('cross over')
      
    • 通过 Hub 获取事件服务

      # main.py
      
      from noba import core
      if __name__ == '__main__':
          event_service = core.make('event')
          cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")    
      
          service_obj = cross_over_hub.manager
          print(service_obj == event_service) # True
      

订阅事件

通过 watch 方法可以订阅在 Hub 中定义的事件。watch 接受 3 个参数:事件名回调函数,回调函数可以接受事件通知时传递的数据。第 3 个参数是个布尔值 ,决定该订阅是否可以多次监听。默认为 False,只监听一次。

# main.py

from noba import core

if __name__ == '__main__':
    event_service = core.make('event')
    cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")

    cross_over_hub.watch('cross close price', lambda data:print(data), True)  # True 表示该订阅可以多次监听。False 是只监听一次

上面是面向过程的事件订阅,还可以面向对象方式来订阅事件(订阅者模式)

from noba import core

event_service = core.make('event')

class Purchase(event_service):
    def subscribe(self, event):
        cross_over_hub = self.get_hub('cross over')

        # 订阅事件
        cross_over_hub.watch(event, lambda data:print(f"moving average price is {data['moving_average_price']}, close price is {data['close_price']}。cross over!"), True)

if __name__ == '__main__':

    # 创建一个命名为 cross over 的hub,该 hub 包含两个事件:'cross close price', 'cross open  price'
    cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")

    Purchase().subscribe('cross close price')

事件通知

通过 fire 方法可以触发定义在 Hub 中的事件。fire 传入两个参数:事件名数据。数据会传递给订阅者的回调函数中。如下代码会打印出:"moving average price is 12, close price is 10。cross over!"

# main.py

from noba import core

if __name__ == '__main__':
    event_service = core.make('event')
    cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")


    cross_over_hub.watch('cross close price', lambda data:print(f"moving average price is {data['moving_average_price']}, close price is {data['close_price']}。cross over!"), True)
    cross_over_hub.fire('cross close price', {"moving_average_price":12, "close_price":10})


订阅者模式下的事件通知:

# main.py

from noba import core

event_service = core.make('event')

class Purchase(event_service):
    def subscribe(self, event):
        cross_over_hub = self.get_hub('cross over')

        # 订阅事件
        cross_over_hub.watch(event, lambda data:print(f"moving average price is {data['moving_average_price']}, close price is {data['close_price']}。cross over!"), True)

if __name__ == '__main__':

    # 创建一个命名为 cross over 的hub,该 hub 包含两个事件:'cross close price', 'cross open  price'
    cross_over_hub = event_service.hub(['cross close price', 'cross open  price']).name("cross over")

    Purchase().subscribe('cross close price')
    cross_over_hub.fire('cross close price', {"moving_average_price":12, "close_price":10})

* 当然通知也可以用面向对象来改写,只需要继承事件服务就可以,代码略