同步风格的消息¶
问题¶
有开发者在 issue 提了这个问题:
怎么处理异步发送的消息,如何等待它成功执行返回?
同步通信的过程可以由下图表示:
如果你熟悉 http,就会看出它们是相似的。
如果你熟悉 ROS,可能会觉得,同步模式类似 service,异步模式类似 action。
思路¶
无论是 websocket 还是 ZeroMQ pub/sub,都是异步的。
我们如何在异步中实现,同步模式呢?策略是使用 message_id。
目前 Scratch EIM 已经支持同步风格的积木(阻塞风格)。
实现¶
这些同步风格的积木需要与同步风格的 CodeLab Adapter 插件一起使用。让我们来实现它。
Sync extension¶
功能依然是反转字符串,在同步插件中,完成反转字符串功能,需要一秒钟。
以下是插件源码:extension_sync_helloworld.py
import time from codelab_adapter.core_extension import Extension class SyncHelloWorldExtension(Extension): def __init__(self): super().__init__() self.NODE_ID = "eim" def send_message_to_scratch(self, payload): message = self.message_template() message["payload"] = payload self.publish(message) def extension_message_handle(self, topic, payload): self.logger.info(f'the message payload from scratch: {payload}') content = payload["content"] if type(content) == str: content_send_to_scratch = content[::-1] # 反转字符串 time.sleep(1) payload["content"] = content_send_to_scratch self.send_message_to_scratch(payload) def run(self): while self._running: time.sleep(1) export = SyncHelloWorldExtension
通过与 hello world 教程的对比,可以看出同步消息与异步消息在 CodeLab Adapter 插件一侧的区别:通过返回来自 Scratch 的消息中携带的 message_id(message_id 在 payload 中,通过观察日志,可以看到 payload 内部细节)。让请求者得知当前消息被响应了。
同步消息与异步消息,在 Scratch 插件一侧的区别表现为不同的积木(是否wait/等待
),js 代码层面的差异表现在:发送消息的函数不同,这部分你可以直接使用 EIM 插件,可以不做深究。
刷新 Web UI,点击运行extension_hello_world.py
,接着你就可以在 Scratch 中与你的插件交互了。
如果你将 5 个上图中的积木拼在一起,它们将依次运行,一共耗时 5 秒。
FAQ¶
如果某个积木,在 wait 的过程中,没有得到响应会发生什么?
超时时间是 5 秒,所以 5 秒后会继续往下运行。