swift 如何使用AsyncTimerSequence获取初始时钟,然后在指定的时间间隔内开始迭代?

lnxxn5zx  于 11个月前  发布在  Swift
关注(0)|答案(3)|浏览(92)

我一直在从AsyncAlgorithms探索AsyncTimerSequence,发现它是一个简单的解决方案,可以连续地从await函数向侦听器发出元素。
我的问题是序列只在给定的时间间隔后发出一个值。我通过查看source code知道这是设计好的。然而,我想在某个函数开始监听序列后立即发出一个值,然后在指定的时间间隔后发出。
我想我必须创建我自己的AsyncSequence(通过修改AsyncTimerSequence),但我只是想知道是否有一个解决方案,不涉及编写一个新的序列创建器。

bgibtngc

bgibtngc1#

我们可以chain一个异步序列,只包含now(通过async)和定时器序列:

let clock = ContinuousClock()
let timerSequence = AsyncTimerSequence(interval: .seconds(1), clock: clock)
let sequence = chain([clock.now].async, timerSequence)

for await tick in sequence {
    …
}

字符串

cbeh67ev

cbeh67ev2#

比如?

func listen() async -> AsyncThrowingStream<Value> {
    var firstTime = true
    return AsyncThrowingStreamStream {
        if !firstTime {
            try await Task.sleep(someDuration)
        }
        firstTime = false
        return try await emmiter()
    }
}

字符串

92vpleto

92vpleto3#

我通过制作自己的AsyncSequence解决了这个问题,但可能有更好的方法。

public struct AsyncInitialTimerSequence<C: Clock>: AsyncSequence {
    public typealias Element = C.Instant
    
    /// The iterator for an `AsyncInitialTimerSequence` instance.
    public struct Iterator: AsyncIteratorProtocol {
        var clock: C?
        let interval: C.Instant.Duration
        let tolerance: C.Instant.Duration?
        var last: C.Instant?
        
        init(interval: C.Instant.Duration, tolerance: C.Instant.Duration?, clock: C) {
            self.clock = clock
            self.interval = interval
            self.tolerance = tolerance
        }
        
        public mutating func next() async -> C.Instant? {
            guard let clock = self.clock else {
                return nil
            }
            
            if self.last == nil {
                let now = clock.now
                self.last = now
                return now
            }
            
            let next = (self.last ?? clock.now).advanced(by: self.interval)
            do {
                try await clock.sleep(until: next, tolerance: self.tolerance)
            } catch {
                self.clock = nil
                return nil
            }
            let now = clock.now
            self.last = next
            return now
        }
    }
    
    let clock: C
    let interval: C.Instant.Duration
    let tolerance: C.Instant.Duration?
    
    /// Create an `AsyncInitialTimerSequence` with a given repeating interval.
    public init(interval: C.Instant.Duration, tolerance: C.Instant.Duration? = nil, clock: C) {
        self.clock = clock
        self.interval = interval
        self.tolerance = tolerance
    }
    
    public func makeAsyncIterator() -> Iterator {
        Iterator(interval: interval, tolerance: tolerance, clock: clock)
    }
}

extension AsyncInitialTimerSequence {
    /// Create an `AsyncInitialTimerSequence` with a given repeating interval.
    public static func repeating(every interval: C.Instant.Duration, tolerance: C.Instant.Duration? = nil, clock: C) -> AsyncInitialTimerSequence<C> {
        return AsyncInitialTimerSequence(interval: interval, tolerance: tolerance, clock: clock)
    }
}

extension AsyncInitialTimerSequence where C == SuspendingClock {
    /// Create an `AsyncInitialTimerSequence` with a given repeating interval.
    public static func repeating(every interval: Duration, tolerance: Duration? = nil) -> AsyncInitialTimerSequence<SuspendingClock> {
        return AsyncInitialTimerSequence(interval: interval, tolerance: tolerance, clock: SuspendingClock())
    }
}

extension AsyncInitialTimerSequence: Sendable { }
extension AsyncInitialTimerSequence.Iterator: Sendable { }

字符串

相关问题