Никогда не возвращайся в плоской карте с Swift's Combine - PullRequest
0 голосов
/ 18 октября 2019

В RxSwift оператор flatMap может легко вернуть не завершающее Observable. Допустим, у нас есть такая (надуманная и глупая) наблюдаемая цепочка:

let repo = DataRepository()

Observable
    .just(Int.random(in: 0 ..< 1000))
    .flatMap { num -> Observable<String> in
        if num == 42 {
            return .never()
        }

        return repo
            .fetchData()
            .filter { $0.statusCode == 200 }
            .map { $0.data.title }
    }

С Combine самое близкое, что я могу получить, это что-то вроде этого (не пытался скомпилировать, но вы поняли идею):

Just(Int.random(in: 0 ..< 1000))
    .flatMap { num -> AnyPublisher<String, Never> in
        if num == 42 {
            return Empty<String, Never>(completeImmediately: false).eraseToAnyPublisher()
        }

        return repo
            .fetchData()
            .filter { $0.statusCode == 200 }
            .map { $0.data.title }
            .eraseToAnyPublisher()
    }

Я в порядке с этим решением, но я вижу две проблемы, которых мне хотелось бы избежать:

1) Решение Combine несколько более многословно, чтобы достичь того же самого.

2) Мне нужно вызвать eraseToAnyPublisher() на обоих возвращенных издателях, иначе возвращаемые типы не совпадают. Я считаю, что вызов eraseToAnyPublisher() не позволяет Swift применить некоторые внутренние оптимизации (я больше не могу найти статью, которую читаю об этой оптимизации; информации об этом мало)

Есть ли у кого-нибудь лучший подход к решению этой проблемы? пример сценария?

1 Ответ

0 голосов
/ 19 октября 2019

Попытайтесь поднять любую условную логику в операторы.

Условия, при которых вы излучаете что-то вроде Observable.never, лучше всего регистрируются в фильтре, таким образом вы получаете поведение "никогда" бесплатно.

Пример:

Just(Int.random(in: 0 ..< 1000))
        .filter { $0 != 42 }
        .flatMap {
            return repo
                .fetchData()
                .filter { $0.statusCode == 200 }
                .map { $0.data.title }
        }

Я не знаю достаточно о типах в DataRepository, чтобы знать, нужно ли вводить стирание внутри закрытия flatMap.

...