合并CombineLatest不等待上一个操作触发

如果您在Playgroud中尝试以下代码:

import Combine
import Foundation

struct User {
    let name: String
}

private var subscriptions = Set<AnyCancellable>()
var didAlreadyImportUsers = false
var users = [User]()

func importUsers() -> Future<Bool,Never> {
    Future { promise in
        DispatchQueue.global(qos: .userInitiated).async {
            sleep(5)
            users = [User(name: "John"),User(name: "Jack")]
            promise(.success(true))
        }
    }
}

func getUsers(age: Int? = nil) ->Future<[User],Error> {
    Future { promise in
        promise(.success(users))
    }
}

var usersPublisher: AnyPublisher<[User],Error> {
    if didAlreadyImportUsers {
        return getUsers().eraseToAnyPublisher()
    } else {
        return importUsers()
            .setfailureType(to: Error.self)
            .combineLatest(getUsers())
            .map { $0.1 }
            .eraseToAnyPublisher()
    }
}

usersPublisher
    .sink(receiveCompletion: { completion in
    print(completion)
},receiveValue: { value in
    print(value)
}).store(in: &subscriptions)

它将打印:

[]
finished

但我希望:

[User(name: "John"),User(name: "Jack")]
finished

如果我删除带有sleep(5)的行,则它将正确打印结果。似乎是异步问题。似乎.combineLatest(getUsers())不在等待importUsers()我以为combineLatest正在照顾那个?我在这里想念什么?

(在我的真实代码中,Core Data操作长期运行,而不是sleep

iCMS 回答:合并CombineLatest不等待上一个操作触发

CombineLatest将按照您正确预期的那样等待,但是对于您而言,getUsers已经准备好一个值,即[];即users运行时getUsers是什么。

实际上,您不需要使用CombineLatest来“等待”,直到发生一些异步操作为止。您可以连锁发布者:

return importUsers()
           .setFailureType(to: Error.self)
           .flatMap { _ in
               getUsers()
           }
           .eraseToAnyPublisher()

实际上,如果您可以假设在getUsers之后填充users,甚至不需要importUsers

return importUsers()
           .map { _ in
               self.users
           }
           .eraseToAnyPublisher()
本文链接:https://www.f2er.com/2168308.html

大家都在问