我最近開始研究《組合》,遇到了某個問題。 首先,我將描述我在做什么。 我試圖使用Clean Architecture 這里你可以看到我的資源庫
protocol Repository {
func test()
}
class MockRepository: Repository {
func test() {
sleep(3)
}
}
然后我創建了UseCase
class UseCaseBase< TInput, TOutput> {
var task: TOutput? { return nil }
var repository: Repository
init(_ repository: Repository) {
self.repository = repository
}
func execute(with payload: TInput) -> AnyPublisher<TOutput, Never> {
return AnyPublisher(Future< TOutput, Never> { promise in.
promise(.success(self.task!))
})
.擦除到任何出版商()
}
}
class MockUseCase。UseCaseBase<String, Int> {
override var task: Int? {
repository.test()
return 1 ?
}
}
然后在一個init塊ContentView中,我做了這樣的事情
init() {
let useCase = MockUseCase(MockRepository()
var cancellables = Set<AnyCancellable>()
useCase.execute(with: "String"/span>)
.sink(receiveValue: { value in 價值
print(value)
})
.store(in: & cancellables)
print(" Started")
}
首先,我想獲得
"開始"
然后在sleep(3)之后
值為 "1"
現在我得到 "1",然后是 "開始"
uj5u.com熱心網友回復:
我要說的第一件事是,你需要持有對cancellables的參考,否則當你在鏈上添加異步處理時,你的發布者將自動被取消。把它從你的init方法中移出,放到一個屬性中。
你也可以擺脫sleep,并簡單地在你選擇的佇列中鏈入一個Delay發布器。我選擇了main.
struct SomeThing {
var cancellables = Set<AnyCancellable>()
init() {
MockUseCase(MockRepository()
.execute(with: "String")
.delay(for: 3.0, scheduler: DispatchQueue.main)
.sink(receiveValue: { print($0) } )
.store(in: & cancellables)
print(" Started")
}
}
class MockRepository: Repository {
func test() {
//sleep(3)。
}
}
另一個選擇是擺脫delay,擺脫sleep,異步地履行你的承諾:
struct SomeThing {
var cancellables = Set<AnyCancellable>()
init() {
MockUseCase(MockRepository()
.execute(with: "String")
.sink(receiveValue: { print($0) } )
.store(in: & cancellables)
print(" Started")
}
}
class MockRepository: Repository {
func test() {
//sleep(3)。
}
}
func execute(with payload: TInput) -> AnyPublisher<TOutput, Never> {
return Future<TOutput, Never> { promise in
DispatchQueue.main.asyncAfter(deadline: .now() 3) {
promise(.success(self.task!)
}
}
.擦除到任何出版商()
}
uj5u.com熱心網友回復:
你的sleep(3)呼叫在主執行緒上運行,這意味著它阻止了任何其他操作,包括列印 "開始 "文本的代碼。
我不會喋喋不休地談論阻塞主執行緒有多么糟糕,這是眾所周知的資訊,但這就是你看到你所問的行為的原因。
我在你的問題中沒有看到任何執行緒切換的代碼,所以如果你希望實作某種異步性,那么你可以采用Rob的解決方案,即使用dispatch(after:),或者在另一個執行緒上做運動(睡眠):
func execute(with payload: TInput) -> AnyPublisher<TOutput, Never> {
return AnyPublisher(Future< TOutput, Never> { promise in.
DispatchQueue.global().async {
promise(.success(self.task!))
}
})
.eraseToAnyPublisher()
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/318018.html
標籤:
