使用 Combine 具有不同值类型的简单 Future 链接

Simple Future chaining that have different value types using Combine

我要应用的逻辑是:

如果我们已经导入了用户,我们就只获取它们,否则先导入用户,然后再获取它们。这是我的尝试:

import Combine

struct User {
    let name: String
}

var didAlreadyImportUsers = false

// Import the users and return true of false 
var importUsers: Future<Bool, Never> {
    Future { promise in
        promise(.success(true))
    }
}

var fetchUsers: Future<[User], Error> {
    Future { promise in
        promise(.success([User(name: "John"), User(name: "Jack")]))
    }
}

var users: Future<[User], Error> {
    if didAlreadyImportUsers {
        return fetchUsers
    } else {
        return importUsers.setFailureType(to: Error.self)
            .combineLatest(fetchUsers)
            .map { [=10=].1 }
    }
}

我得到一个错误:

Cannot convert return expression of type
'Publishers.Map<Publishers.CombineLatest<Publishers.SetFailureType<Future<Bool, Never>, Error>, Future<[User], Error>>, [User]>' 
to return type 'Future<[User], Error>'

知道如何获得链接为 Future<[User], Error> 的结果吗?

太近了!只需擦除类型:

var users: AnyPublisher<[User], Error> {
    if didAlreadyImportUsers {
        return fetchUsers.eraseToAnyPublisher()
    } else {
        return importUsers.setFailureType(to: Error.self)
            .combineLatest(fetchUsers)
            .map { [=10=].1 }.eraseToAnyPublisher()
    }
}

你可能会说:等等,那不是我说要做的;我想 return 它作为未来。好吧,不要想要那个!它 不是 未来;这是一些可怕的 Future-plus-CombineLast-plus-Map 东西。你不想知道它是什么。你只想知道它的输出类型和失败类型。

这里的重点是一个出版商和另一个出版商一样好;它们可以互换使用,只要它们的类型匹配。这就是提供 AnyPublisher 的原因:这样您就可以做到这一点。基本上,AnyPublisher 是您在发布者类型之间进行转换的方式:您只需将所有内容都转换为 AnyPublisher。