Combine操作符Timing示例


2天前 3次点击 来自 移动端

标签: Swift

Timing 时间

时间控制 Controlling timing

debounce


debounce最经典的使用场景有

搜索框输入:

处理搜索框过于频繁发起网络请求的问题,每当用户输入一个字符的时候,都发起网络请求,会浪费一部分网络资源,通过debounce,可以实现,当用户停止输入0.5秒再发送请求。

按钮点击:

处理按钮的连续点击问题,debounce只接收0.5秒后的最后一次点击事件,因此自动忽略了中间的多次连续点击事件

let bounces: [(Int, TimeInterval)] = [
    (0, 0),
    (1, 0.2), // 0.2s interval since last index
    (2, 1), // 0.7s interval since last index
    (3, 1.2), // 0.2s interval since last index
    (4, 1.5), // 0.2s interval since last index
    (5, 2), // 0.5s interval since last index
]

let subject = PassthroughSubject<Int, Never>()
let cancellable = subject
    .debounce(for: .seconds(0.5), scheduler: RunLoop.main)
    .sink { index in
        print("Received index \(index)")
    }

for bounce in bounces {
    DispatchQueue.main.asyncAfter(deadline: .now() + bounce.1) {
        subject.send(bounce.0)
    }
}

delay

延迟发送数据

let bounces: [(Int, TimeInterval)] = [
    (0, 0.2),
    (1, 0.5),
]

let subject = PassthroughSubject<Int, Never>()
let cancellable = subject
    .delay(for: 1.0,
           scheduler: RunLoop.main)
    .sink { index in
        print("Received index \(index) in \(Date().timeIntervalSince1970)")
    }

for bounce in bounces {
    DispatchQueue.main.asyncAfter(deadline: .now() + bounce.1) {
        subject.send(bounce.0)
        print("send \(Date().timeIntervalSince1970)")
    }
}

measureInterval

记录publisher发送数据的间隔时间

let bounces: [(Int, TimeInterval)] = [
    (0, 0.2),
    (1, 1.5),
]

let subject = PassthroughSubject<Int, Never>()
let cancellable = subject
    .measureInterval(using: RunLoop.main)
    .sink { print($0) }

for bounce in bounces {
    DispatchQueue.main.asyncAfter(deadline: .now() + bounce.1) {
        subject.send(bounce.0)
    }
}

throttle

设定一个固定时间间隔的时间窗口,latest可以指定发送的数据是该窗口内的第一个数据还是最后一个数据

let bounces: [(Int, TimeInterval)] = [
    (1, 0.2),
    (2, 1),
    (3, 1.2),
    (4, 1.4),
]

let subject = PassthroughSubject<Int, Never>()
let cancellable = subject
    .throttle(for: 0.5,
              scheduler: RunLoop.main,
              latest: true)
    .sink { index in
        print("Received index \(index) in \(Date().timeIntervalSince1970)")
    }

for bounce in bounces {
    DispatchQueue.main.asyncAfter(deadline: .now() + bounce.1) {
        subject.send(bounce.0)
    }
}

throttle 与 debounce 的区别:
throttle按照固定的顺序排列时间窗口,在时间窗口的结尾处发送数据,而debounce每次接收到新数据,都会重新开启一个新的时间窗口,同时取消之前的时间窗口

timeout

超时设置

enum MyError: Error {
    case timeout
}

let subject = PassthroughSubject<Int, Never>()
let cancellable = subject
    .setFailureType(to: MyError.self)
    .timeout(.seconds(1),
             scheduler: RunLoop.main,
             customError: {
                 MyError.timeout
             })
    .sink(receiveCompletion: { print($0) }, receiveValue: { print($0) })

DispatchQueue.main.asyncAfter(deadline: .now() + 1.2) {
    subject.send(1)
}

Made with in Shangrao,China By Devler.

Copyright © Devler 2012 - 2022

赣ICP备19009883号-1