我认为您只想过滤所有项目,然后附加:
,而不是
ignoreOutput
let fooThenBar = foo.first()
.filter { _ in false }
.append(bar)
您可能会发现更好地重命名dropAll()
:
extension Publisher {
func dropAll() -> Publishers.Filter<Self> { filter { _ in false } }
}
let fooThenBar = foo.first()
.dropAll()
.append(bar)
潜在的问题是,ignoreAll()
生成的Publisher的输出为Never(从不),这通常是有道理的。但是在这种情况下,您只想获取值而不改变类型,那就是过滤。
,
通过与@RobNapier进行的深入讨论,我们得出的结论是,flatMap { Empty }.append(otherPublisher)
解决方案在两个发布者的输出不同时是最佳的。因为我想在first / base /'foo'发布者完成后使用它,所以我在Publishers.IgnoreOutput
上写了一个扩展名,结果是:
解决方案
protocol BaseForAndThen {}
extension Publishers.IgnoreOutput: BaseForAndThen {}
extension Combine.Future: BaseForAndThen {}
extension Publisher where Self: BaseForAndThen,Self.Failure == Never {
func andThen<Then>(_ thenPublisher: Then) -> AnyPublisher<Then.Output,Never> where Then: Publisher,Then.Failure == Failure {
return
flatMap { _ in Empty<Then.Output,Never>(completeImmediately: true) } // same as `init()`
.append(thenPublisher)
.eraseToAnyPublisher()
}
}
用法
在我的用例中,我想控制/了解何时基本发布者,因此我的解决方案基于此。
与ignoreOutput
由于第二个发布者(在appleSubject
以下)在第一个发布者完成之前不会开始生成元素(输出值),因此我使用first()
运算符(还有一个{{3} }运算符),使bananaSubject
在一次输出后结束。
bananaSubject.first().ignoreOutput().andThen(appleSubject)
与Future
Future
仅产生一个元素,然后完成。
futureBanana.andThen(applePublisher)
测试
这是完整的单元测试(last()
)
import XCTest
import Combine
protocol Fruit {
var price: Int { get }
}
typealias ? = Banana
struct Banana: Fruit {
let price: Int
}
typealias ? = Apple
struct Apple: Fruit {
let price: Int
}
final class CombineAppendDifferentOutputTests: XCTestCase {
override func setUp() {
super.setUp()
continueAfterFailure = false
}
func testFirst() throws {
try doTest { bananaPublisher,applePublisher in
bananaPublisher.first().ignoreOutput().andThen(applePublisher)
}
}
func testFuture() throws {
var cancellable: Cancellable?
try doTest { bananaPublisher,applePublisher in
let futureBanana = Future<?,Never> { promise in
cancellable = bananaPublisher.sink(
receiveCompletion: { _ in },receiveValue: { value in promise(.success(value)) }
)
}
return futureBanana.andThen(applePublisher)
}
XCTAssertNotNil(cancellable)
}
static var allTests = [
("testFirst",testFirst),("testFuture",testFuture),]
}
private extension CombineAppendDifferentOutputTests {
func doTest(_ line: UInt = #line,_ fooThenBarMethod: (AnyPublisher<?,Never>,AnyPublisher<?,Never>) -> AnyPublisher<?,Never>) throws {
// GIVEN
// Two publishers `foo` (?) and `bar` (?)
let bananaSubject = PassthroughSubject<Banana,Never>()
let appleSubject = PassthroughSubject<Apple,Never>()
var outputtedFruits = [Fruit]()
let expectation = XCTestExpectation(description: self.debugDescription)
let cancellable = fooThenBarMethod(
bananaSubject.eraseToAnyPublisher(),appleSubject.eraseToAnyPublisher()
)
.sink(
receiveCompletion: { _ in expectation.fulfill() },receiveValue: { outputtedFruits.append($0 as Fruit) }
)
// WHEN
// a send apples and bananas to the respective subjects and a `finish` completion to `appleSubject` (`bar`)
appleSubject.send(?(price: 1))
bananaSubject.send(?(price: 2))
appleSubject.send(?(price: 3))
bananaSubject.send(?(price: 4))
appleSubject.send(?(price: 5))
appleSubject.send(completion: .finished)
wait(for: [expectation],timeout: 0.1)
// THEN
// A: I the output contains no banana (since the bananaSubject publisher's output is ignored)
// and
// B: Exactly two apples,more specifically the two last,since when the first Apple (with price 1) is sent,we have not yet received the first (needed and triggering) banana.
let expectedFruitCount = 2
XCTAssertEqual(outputtedFruits.count,expectedFruitCount,line: line)
XCTAssertTrue(outputtedFruits.allSatisfy({ $0 is ? }),line: line)
let apples = outputtedFruits.compactMap { $0 as? ? }
XCTAssertEqual(apples.count,line: line)
let firstApple = try XCTUnwrap(apples.first)
let lastApple = try XCTUnwrap(apples.last)
XCTAssertEqual(firstApple.price,3,line: line)
XCTAssertEqual(lastApple.price,5,line: line)
XCTAssertNotNil(cancellable,line: line)
}
}
,
只要您使用 .ignoreOutput()
,就可以安全地将“丑陋的”.flatMap { _ in Empty<Fruit,Never>() }
替换为简单的 .map { Fruit?.none! }
,它无论如何都不会被调用,只会更改输出类型。
本文链接:https://www.f2er.com/3156943.html