swift cancel Task inside Future(async/await with合并)

pod7payv  于 2023-04-04  发布在  Swift
关注(0)|答案(1)|浏览(103)

我决定在合并框架中使用async/ await。我在Future类上使用了一个扩展,并在里面放了一个Task块。看起来不错,我得到了一个结果或错误,但我对此有问题,如果我想取消我的async函数的进度,我只取消了发布者。
我用下面的扩展,我学到了https://tanaschita.com/20220822-bridge-async-await-to-combine-future/

extension Future where Failure == Error {

    convenience init(taskPriority: TaskPriority? = nil, asyncFunc: @escaping () async throws -> Output) {
        self.init { promise in
            Task(priority: taskPriority) {
                do {
                    let result = try await asyncFunc()
                    promise(.success(result))
                } catch {
                    promise(.failure(error))
                }
            }
        }
    }
}

并编写两个用于将数据保存到核心数据中的辅助函数(例如):

func saveIntoCoreData() throws {
        throw DatabaseError.canNotSave
    }

    func doSomeThing() async throws -> String {
        return try await withCheckedThrowingContinuation { continuation in
            do {
                Thread.sleep(forTimeInterval: 5)
                try saveIntoCoreData()
                continuation.resume(with: .success("Result"))
            } catch {
                continuation.resume(with: .failure(error))
            }
        }
    }

最后,我用Future调用了这些方法,我希望得到一个cancel错误并停止运行以将数据保存到核心数据中,但刚刚从发布者那里得到一个cancelled事件,数据被保存到核心数据中。

cancelable = Future(taskPriority: .userInitiated) { [weak self] in
            return try await self?.doSomeThing()
        }.eraseToAnyPublisher()
            .sink { completion in
                switch completion {
                case .finished:
                    print("Finished")
                case .failure(let error):
                    print(error.localizedDescription)
                }
            } receiveValue: { value in
                print("result: \(value)")
            }

        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
            self.cancelable?.cancel()
        }

我用try Task.checkCancellation(),但任务没有取消,没有工作。
有没有人有办法阻止任务?

8e2ybdfx

8e2ybdfx1#

期货不能取消,但出版商可以。
使用Ian Keen's AnyPublisher extension
然后您可以:

extension AnyPublisher where Failure == Error {
    init(taskPriority: TaskPriority? = nil, asyncFunc: @escaping () async throws -> Output) {
        self.init { subscriber in
            let task = Task(priority: taskPriority) {
                do {
                    subscriber.send(try await asyncFunc())
                    subscriber.send(completion: .finished)
                } catch {
                    subscriber.send(completion: .failure(error))
                }
            }
            return AnyCancellable { task.cancel() }
        }
    }
}

相关问题