Pharo技术问询:如何将块/定时任务块内变量返回至方法
在Pharo中处理异步任务里的变量传递
这个问题的核心在于TaskScheduler的任务是异步执行的——你的updateMethod会在启动调度器后立刻完成并返回,而那个每隔60秒跑一次的块是在后台单独执行的。所以没法让方法直接“返回”每次的data,而是需要换一种方式来处理每次生成的data。下面给你几种实用的实现思路:
1. 用实例变量存储最新数据
如果只是需要随时获取最新的data值,可以把data从方法的临时变量改成类的实例变量,这样每次任务块执行时都会更新这个变量,其他地方可以随时读取:
首先给你的类添加实例变量data,并生成访问器方法:
Class>>data ^ data ifNil: [ data := Dictionary new ] "给个默认空字典,避免nil报错" Class>>data: aJsonObject data := aJsonObject
然后修改updateMethod:
Class>>updateMethod "This is a method" | scheduler | scheduler := TaskScheduler new. scheduler start. "refresh every 60 seconds" scheduler do: [ | client response | client := ZnClient new. response := client get: 'https://MyServer/json'. Transcript show: 'Refreshing......'; cr. self data: (NeoJSONReader fromString: response) ] "更新实例变量" every: 60 seconds
之后你就可以通过yourClassInstance data随时获取最新的JSON数据了。
2. 传入回调块处理每次数据
如果每次获取到data后需要立刻执行特定逻辑(比如更新UI、存储到本地),可以把处理逻辑做成回调块传给方法:
Class>>updateMethodWithCallback: processingBlock "This method takes a block to handle each new data batch" | scheduler | scheduler := TaskScheduler new. scheduler start. scheduler do: [ | client response jsonData | client := ZnClient new. response := client get: 'https://MyServer/json'. Transcript show: 'Refreshing......'; cr. jsonData := NeoJSONReader fromString: response. processingBlock value: jsonData ] "执行回调处理数据" every: 60 seconds
使用的时候直接传入处理逻辑:
yourInstance updateMethodWithCallback: [ :newData | "这里写你要做的事情,比如打印到Transcript或者更新界面" Transcript show: 'New data received: ', newData printString; cr. ]
3. 用Announcement发布数据更新通知
如果你的代码需要解耦——比如多个对象都需要知道数据更新了,Pharo的Announcement系统是个很好的选择:
首先定义一个自定义通知类:
DataUpdatedAnnouncement subclass: #DataRefreshedAnnouncement instanceVariableNames: 'data' classVariableNames: '' package: 'YourPackageName' DataRefreshedAnnouncement>>data ^ data DataRefreshedAnnouncement>>data: anObject data := anObject
然后修改updateMethod来发布通知:
Class>>updateMethod "This is a method" | scheduler | scheduler := TaskScheduler new. scheduler start. scheduler do: [ | client response jsonData | client := ZnClient new. response := client get: 'https://MyServer/json'. Transcript show: 'Refreshing......'; cr. jsonData := NeoJSONReader fromString: response. "发布数据更新通知" DataRefreshedAnnouncement new data: jsonData; announce ] every: 60 seconds
最后在需要接收数据的对象里订阅通知:
"在你的UI类或者其他处理类里" self when: DataRefreshedAnnouncement do: [ :announcement | | latestData | latestData := announcement data. "处理最新数据" Transcript show: 'Received updated data: ', latestData printString; cr. ]
顺便提下原代码的小问题:
- 原代码里
a get: 'https://MyServer/json'的a没有定义,需要创建ZnClient实例来发起请求; NeoJSONReader fromString: a contents; cr.语法错误,分号用于同一接收者的消息链,这里应该分开写,而且ZnClient的get:方法直接返回响应内容,不需要再取contents。
内容的提问来源于stack exchange,提问作者ludo
相关产品推荐
相关产品推荐

