Asynchronous 我怎么能';丑';这些嵌套的异步部分,在F中#
首先,代码如下:Asynchronous 我怎么能';丑';这些嵌套的异步部分,在F中#,asynchronous,f#,Asynchronous,F#,首先,代码如下: let getCandlesFromAsync (exchange: IExchange) (instrument: Instrument) (interval: TimeSpan) (fromTime: DateTime) (toTime: DateTime) = async { let rec getAsync (c: CandleData list) (f: DateTime) (t: DateTime) = async {
let getCandlesFromAsync (exchange: IExchange) (instrument: Instrument) (interval: TimeSpan) (fromTime: DateTime) (toTime: DateTime) =
async {
let rec getAsync (c: CandleData list) (f: DateTime) (t: DateTime) =
async {
//info $"requesting {instrument}: {f} - {t}"
let! candles = exchange.GetCandlesAsync(instrument, interval, f, t)
if candles.IsError then
return (failwith candles.GetError.Describe)
else
//info $"received data {instrument}: {candles.Get.[0].Timestamp} - {candles.Get.[^0].Timestamp}"
let c = c @ candles.Get
if c.[^0].Timestamp < t - interval then
return! getAsync c (c.[^0].Timestamp + interval) t
else
return c
}
let cache = DataCache.getCache instrument
let candlesFromCache = getCandlesFromCache cache interval fromTime toTime
let firstTimestamp =
match candlesFromCache.IsEmpty with
| true -> fromTime
| false -> candlesFromCache.[^0].Timestamp + interval
// check if we need some new data
let downloadedCandles =
async {
if firstTimestamp < toTime then
let! x = getAsync [] firstTimestamp toTime
putCandlesInCache cache x
return x
else
return []
}
let! d = downloadedCandles
return candlesFromCache @ d
}
让getCandlesFromAsync(exchange:IEExchange)(仪表:仪表)(间隔:TimeSpan)(fromTime:DateTime)(toTime:DateTime)=
异步的{
let rec getAsync(c:CandleData列表)(f:DateTime)(t:DateTime)=
异步的{
//信息$“正在请求{instrument}:{f}-{t}”
let!candles=exchange.getCandleAsync(仪表、间隔、f、t)
如果你是伊瑟罗那么
返回(failwith蜡烛。GetError。描述)
其他的
//info$“收到的数据{instrument}:{cands.Get.[0]。时间戳}-{cands.Get.[^0]。时间戳}”
让c=c@蜡烛。获取
如果c.[^0]。则时间戳fromTime
|false->candlesFromCache。[^0]。时间戳+间隔
//检查我们是否需要一些新数据
让下载的蜡烛=
异步的{
如果firstTimestamp
这段代码应该是从交易所下载价格蜡烛。它必须定期运行并跟上新数据
因为我需要一系列时间戳中的数据,所以我尝试缓存以前从exchange请求的数据。在不断前进的范围内,我只需检查范围内已有多少数据,以及需要获取多少数据
代码分为几个部分:
- 从缓存中获取某个时间范围的数据的代码(此处未发布,但不相关)。它返回CandleData列表
- 从exchange请求时间范围数据的代码(getAsync),它返回async
- 一小段代码,用于确定缺少的内容并将这些部分粘在一起(函数的后半部分)
必须有一个更干净的方法来做到这一点,但我不知道怎么做。欢迎提出任何建议 分离功能是最佳实践。它不一定会减少
async
s的数量,但它会使代码更干净、更容易理解
从exchange下载的功能可能是独立的:
let downloadFromExchange (exchange: IExchange) (instrument: Instrument) (interval: TimeSpan) (f: DateTime) (t: DateTime) =
let rec getAsync (previousCandles: CandleData list) (f: DateTime) =
async {
//info $"requesting {instrument}: {f} - {t}"
if f < t then return previousCandles else
let! candles = exchange.GetCandlesAsync(instrument, interval, f, t)
if candles.IsError then
return (failwith candles.GetError.Describe)
else
//info $"received data {instrument}: {candles.Get.[0].Timestamp} - {candles.Get.[^0].Timestamp}"
let c = previousCandles @ candles.Get
match c.[^0].Timestamp + interval with
| fr when fr < t -> return! getAsync c fr
| _ -> return c
}
getAsync [] f
我将条件
from
放在下载函数中,这样代码就更干净了。所以将整个过程包装在一个异步中不是解决方案吗?我想有些语句打破了这个流程,我需要单独包装它们?
let getCandlesFromAsync exchange (instrument: Instrument) (interval: TimeSpan) (fromTime: DateTime) (toTime: DateTime) =
async {
let cache = DataCache.getCache instrument
let candlesFromCache = getCandlesFromCache cache interval fromTime toTime
let firstTimestamp =
match candlesFromCache.IsEmpty with
| true -> fromTime
| false -> candlesFromCache.[^0].Timestamp + interval
let! x = downloadFromExchange exchange instrument interval firstTimestamp toTime
putCandlesInCache cache x
return candlesFromCache @ x
}