Combine -- 限流

2021-02-24  本文已影响0人  jancywen

debounce

debounce 又叫做 “防抖”:Publisher 在接收到第一个值后,并不是立即将它发布出去,而是会开启一个内部计时器,当一定时间内没有新的事件来到,再将这个值进行发布。如果在计时期间有新的事件,则重置计时器并重复上述等待过程。

extension String {
    //将原始的url编码为合法的url
    public func urlEncoded() -> String? {
        let encodeUrlString = self.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
        return encodeUrlString
    }
     
    //将编码后的url转换回原始的url
    public func urlDecoded() -> String? {
        return self.removingPercentEncoding
    }
    
    // 去除首尾空格
    public func removeWhitespaces() -> String {
        return self.trimmingCharacters(in: .whitespaces)
    }
}

struct Response: Decodable {
    struct Args: Decodable {
        let foo: String
    }
    let args: Args?
}

let searchText = PassthroughSubject<String, Never>()
searchText
    .scan("", { "\($0) \($1)"})
    .debounce(for: .seconds(3), scheduler: RunLoop.main)
    .compactMap{$0.removeWhitespaces().urlEncoded()}
    .flatMap { text in
        return URLSession.shared
            .dataTaskPublisher(for: URL(string: "https://httpbin.org/get?foo=\(text)")!)
            .subscribe(on: RunLoop.main)
            .map{data, _ in data}
            .decode(type: Response.self, decoder: JSONDecoder())
            .compactMap{$0.args?.foo.urlDecoded()}
            .replaceError(with: text)
    }.eraseToAnyPublisher()
    .subscribe(on: RunLoop.main)
    .print()
    .sink(receiveValue: {_ in})

delay(0) { searchText.send("I") }
delay(1) { searchText.send("Love") }
delay(2) { searchText.send("SwiftUI") }
delay(6) { searchText.send("And") }
delay(8) { searchText.send("Combine") }

// 输出:
// receive subscription: (SubscribeOn)
// request unlimited
// receive value: (I Love SwiftUI)
// receive value: (I Love SwiftUI And Combine)

throttle

在指定的时间间隔内有选择地从上游发布者重新发布元素。在收到一个事件后开始计时,并忽略计时周期内的后续输入。

extension Publisher {

    /// Publishes either the most-recent or first element published by the upstream publisher in the specified time interval.
    ///
    /// - Parameters:
    ///   - interval: The interval at which to find and emit the most recent element, expressed in the time system of the scheduler.
    ///   - scheduler: The scheduler on which to publish elements.
    ///   - latest: A Boolean value that indicates whether to publish the most recent element. If `false`, the publisher emits the first element received during the interval.
    /// - Returns: A publisher that emits either the most-recent or first element received during the specified interval.
    public func throttle<S>(for interval: S.SchedulerTimeType.Stride, scheduler: S, latest: Bool) -> Publishers.Throttle<Self, S> where S : Scheduler
}
上一篇下一篇

猜你喜欢

热点阅读