# 插件服务与事件

插件之间可以通过服务共享功能。事件则用于把一次发生的事情报告给飞块。两者的声明分别见 [services 与 uses](../../reference/services.md) 和 [events](../../reference/events-manifest.md)。

## 服务调用

提供方声明服务 ID、整数版本和方法名，并注册对应处理函数。消费方在 `dependencies` 中声明提供方包的 SemVer 版本范围，并在 `uses` 中写入提供方的插件 ID、服务 ID 和同一个接口版本。安装和启动前两个版本约束必须同时满足；启动消费方会先确认整条依赖链的授权并启动提供方，缺失、冲突或循环依赖会阻止启动。

调用时，飞块先确认消费方已声明该依赖，再确认提供方正在运行且版本匹配。随后调用提供方的函数，把消费方 ID 放在 `request.callerPluginId` 中。这个身份由宿主确定。

提供方返回 JSON 数据后，飞块把结果交给消费方的 Promise。如果提供方未运行、版本不匹配或函数抛出异常，这次调用失败。宿主不会因服务调用自动安装或启用提供方。

## 服务版本

服务版本是正整数，消费方精确匹配。例如，把方法参数从字符串改为对象时，可以把服务版本从 `1` 改为 `2`，同时更新消费方的 `uses`。这和插件包的 SemVer 发布版本是不同的字段。

## 事件交付

后台调用 `events.emit()` 后，宿主检查声明和载荷 Schema，再交付给宿主事件总线。事件为一次性交付，不成为状态快照，当前也不自动触发用户流程。

如果流程需要使用本次计算的结果，从动作函数返回这个结果。如果页面需要读取最新值，发布状态。这样接收方能使用与自己调用方式对应的接口。
