首页 > 解决方案 > 如何排队或等到最后一个合并请求完成?

问题描述

我有一个只需要一次执行一次的功能。我试图避免在尚未完成最后一个请求时调用函数。这就是我想要做的:

import Combine
import Foundation
import PlaygroundSupport

var publisher1 = PassthroughSubject<Bool, Never>()
var publisher2 = PassthroughSubject<Void, Never>()
var cancellable = Set<AnyCancellable>()

func scheduleNotifications() -> Future <Void, Never> {
    Future() { promise in
        print("Started scheduling... \(Date())")

        DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
            promise(.success(()))
        }
    }
}

Publishers.Merge(
    publisher1
        .filter { $0 }
        .map { _ in },
    publisher2
)
.flatMap { scheduleNotifications() }
.sink { print("Complete: \(Date())") }
.store(in: &cancellable)

PlaygroundPage.current.needsIndefiniteExecution = true

如果publisher1publisher2火,那么scheduleNotifications()被称为。但是,在函数完成之前,publisher1可以触发并调用scheduleNotifications()

DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    publisher1.send(true)
}

DispatchQueue.main.asyncAfter(deadline: .now() + 4) {
    publisher1.send(true)
}

这打印:

Started scheduling... 2021-02-07 15:50:25 +0000
Started scheduling... 2021-02-07 15:50:27 +0000
Complete: 2021-02-07 15:50:35 +0000
Complete: 2021-02-07 15:50:38 +0000

这是一个问题,因为scheduleNotifications在添加它们之前会删除所有通知。因此,一秒钟后触发的第二个请求正在擦除第一个请求仍在忙于构建的所有通知。

有没有办法告诉第二场火灾一直持续到scheduleNotifications()完成它已经完成的任何当前正在进行的工作?

标签: swiftcombine

解决方案


maxPublishers您可以使用参数来实现这一点FlatMap。限制为一个会对上游产生背压,直到最后一个生产的发布者完成:

Publishers.Merge(
    publisher1
        .filter { $0 }
        .map { _ in },
    publisher2
)
.flatMap(maxPublishers: .max(1)) {  // <- here
   scheduleNotifications() 
}
.sink { print("Complete: \(Date())") }
.store(in: &cancellable)

推荐阅读