From 338e824b73966ece8022e3cf76f63b9c3f75b0aa Mon Sep 17 00:00:00 2001 From: yaochenfeng <282696845@qq.com> Date: Tue, 10 Jun 2025 00:53:21 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=20update=20DFPromise?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- .../{ServicePromise.swift => DFPromise.swift} | 33 ++++---- ...romiseTests.swift => DFPromiseTests.swift} | 79 +++++++++---------- 3 files changed, 56 insertions(+), 62 deletions(-) rename Sources/DFService/{ServicePromise.swift => DFPromise.swift} (86%) rename Tests/DFServiceTests/{ServicePromiseTests.swift => DFPromiseTests.swift} (79%) diff --git a/README.md b/README.md index c094ca9..52419d9 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,9 @@ struct CounterState: ServiceStateType { ``` -### 实现ServicePromise 异步使用 +### 实现DFPromise 异步使用 -`ServicePromise` 提供了基于 Promise 的异步服务调用方式,适合需要链式调用或异步返回结果的场景。 +`DFPromise` 提供了基于 Promise 的异步服务调用方式,适合需要链式调用或异步返回结果的场景。 #### 示例:异步获取数据 @@ -70,7 +70,7 @@ struct UserInfo: Codable { } // 定义一个 ServicePromise -let promise = ServicePromise { resolver in +let promise = DFPromise { resolver in // 模拟异步网络请求 Task { try await Task.sleep(nanoseconds: 1_000_000_000) // 1秒延迟 diff --git a/Sources/DFService/ServicePromise.swift b/Sources/DFService/DFPromise.swift similarity index 86% rename from Sources/DFService/ServicePromise.swift rename to Sources/DFService/DFPromise.swift index 0abf259..098678c 100644 --- a/Sources/DFService/ServicePromise.swift +++ b/Sources/DFService/DFPromise.swift @@ -1,14 +1,9 @@ -public final class ServicePromise { +public final class DFPromise { public typealias Resolve = (Value) -> Void public typealias Reject = (Error) -> Void public enum State { case pending, fulfilled, rejected } - - // private var successHandler: ((Value) -> Void)? - // private var failureHandler: ((Error) -> Void)? - // private var finalHandler: (() -> Void)? - // private var cancelHandler: (() -> Void)? /// 用于存储成功回调的数组,便于在 Promise 被解析时调用 private var onSuccessHandlers: [(Value) -> Void] = [] /// 用于存储失败回调的数组,便于在 Promise 被拒绝时调用 @@ -50,10 +45,10 @@ public final class ServicePromise { } } -extension ServicePromise { +extension DFPromise { @discardableResult - public func then(_ onFulfilled: @escaping (Value) throws -> U) -> ServicePromise { - return ServicePromise { resolve, reject in + public func then(_ onFulfilled: @escaping (Value) throws -> U) -> DFPromise { + return DFPromise { resolve, reject in let handle = { (value: Value) in do { let result = try onFulfilled(value) @@ -80,9 +75,9 @@ extension ServicePromise { } @discardableResult public func then( - _ onFulfilled: @escaping (Value) throws -> ServicePromise - ) -> ServicePromise { - return ServicePromise { resolve, reject in + _ onFulfilled: @escaping (Value) throws -> DFPromise + ) -> DFPromise { + return DFPromise { resolve, reject in let handle: (Value) -> Void = { value in do { let nextPromise = try onFulfilled(value) @@ -138,11 +133,11 @@ extension ServicePromise { } //拓展Promise 常用函数 转换错误等 - public static func all(_ promises: [ServicePromise]) -> ServicePromise<[Value]> { + public static func all(_ promises: [DFPromise]) -> DFPromise<[Value]> { guard !promises.isEmpty else { return .resolve([]) } - return ServicePromise<[Value]> { resolve, reject in + return DFPromise<[Value]> { resolve, reject in var results = [Value?](repeating: nil, count: promises.count) var remaining = promises.count @@ -160,14 +155,14 @@ extension ServicePromise { } } - public static func resolve(_ value: Value) -> ServicePromise { - return ServicePromise { resolve, _ in + public static func resolve(_ value: Value) -> DFPromise { + return DFPromise { resolve, _ in resolve(value) } } - public static func reject(_ error: Error) -> ServicePromise { - return ServicePromise { _, reject in + public static func reject(_ error: Error) -> DFPromise { + return DFPromise { _, reject in reject(error) } } @@ -190,7 +185,7 @@ extension ServicePromise { } @available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) -extension ServicePromise { +extension DFPromise { public convenience init( _ work: @escaping () async throws -> Value ) { diff --git a/Tests/DFServiceTests/ServicePromiseTests.swift b/Tests/DFServiceTests/DFPromiseTests.swift similarity index 79% rename from Tests/DFServiceTests/ServicePromiseTests.swift rename to Tests/DFServiceTests/DFPromiseTests.swift index 862ac23..7b7dee7 100644 --- a/Tests/DFServiceTests/ServicePromiseTests.swift +++ b/Tests/DFServiceTests/DFPromiseTests.swift @@ -1,5 +1,4 @@ // -// ServicePromiseTests.swift // DFService // // Created by yaochenfeng on 2025/6/7. @@ -9,11 +8,11 @@ import XCTest @testable import DFService -final class ServicePromiseTests: XCTestCase { - +final class DFPromiseTests: XCTestCase { + func testPromiseResolvesImmediately() { let expectation = self.expectation(description: "Immediate resolve") - let promise = ServicePromise { resolve, _ in + let promise = DFPromise { resolve, _ in resolve("immediate") } promise.then { value in @@ -26,7 +25,7 @@ final class ServicePromiseTests: XCTestCase { func testPromiseRejectsImmediately() { enum TestError: Error { case fail } let expectation = self.expectation(description: "Immediate reject") - let promise = ServicePromise { _, reject in + let promise = DFPromise { _, reject in reject(TestError.fail) } promise.catch { error in @@ -38,7 +37,7 @@ final class ServicePromiseTests: XCTestCase { func testThenAfterResolve() { let expectation = self.expectation(description: "Then after resolve") - let promise = ServicePromise.resolve(5) + let promise = DFPromise.resolve(5) promise.then { value in XCTAssertEqual(value, 5) expectation.fulfill() @@ -49,7 +48,7 @@ final class ServicePromiseTests: XCTestCase { func testCatchAfterReject() { enum TestError: Error { case fail } let expectation = self.expectation(description: "Catch after reject") - let promise = ServicePromise.reject(TestError.fail) + let promise = DFPromise.reject(TestError.fail) promise.catch { error in XCTAssertTrue(error is TestError) expectation.fulfill() @@ -59,7 +58,7 @@ final class ServicePromiseTests: XCTestCase { func testFinallyAfterResolve() { let expectation = self.expectation(description: "Finally after resolve") - let promise = ServicePromise.resolve(1) + let promise = DFPromise.resolve(1) promise.finally { expectation.fulfill() } @@ -69,7 +68,7 @@ final class ServicePromiseTests: XCTestCase { func testFinallyAfterReject() { enum TestError: Error { case fail } let expectation = self.expectation(description: "Finally after reject") - let promise = ServicePromise.reject(TestError.fail) + let promise = DFPromise.reject(TestError.fail) promise.finally { expectation.fulfill() } @@ -78,10 +77,10 @@ final class ServicePromiseTests: XCTestCase { func testAllResolves() { let expectation = self.expectation(description: "All resolves") - let p1 = ServicePromise.resolve(1) - let p2 = ServicePromise.resolve(2) - let p3 = ServicePromise.resolve(3) - ServicePromise.all([p1, p2, p3]).then { values in + let p1 = DFPromise.resolve(1) + let p2 = DFPromise.resolve(2) + let p3 = DFPromise.resolve(3) + DFPromise.all([p1, p2, p3]).then { values in XCTAssertEqual(values.sorted(), [1, 2, 3]) expectation.fulfill() } @@ -91,10 +90,10 @@ final class ServicePromiseTests: XCTestCase { func testAllRejectsIfAnyFails() { enum TestError: Error { case fail } let expectation = self.expectation(description: "All rejects if any fails") - let p1 = ServicePromise.resolve(1) - let p2 = ServicePromise.reject(TestError.fail) - let p3 = ServicePromise.resolve(3) - ServicePromise.all([p1, p2, p3]).catch { error in + let p1 = DFPromise.resolve(1) + let p2 = DFPromise.reject(TestError.fail) + let p3 = DFPromise.resolve(3) + DFPromise.all([p1, p2, p3]).catch { error in XCTAssertTrue(error is TestError) expectation.fulfill() } @@ -103,7 +102,7 @@ final class ServicePromiseTests: XCTestCase { func testAllEmptyArray() { let expectation = self.expectation(description: "All with empty array resolves immediately") - ServicePromise.all([]).then { values in + DFPromise.all([]).then { values in XCTAssertEqual(values.count, 0) expectation.fulfill() } @@ -113,7 +112,7 @@ final class ServicePromiseTests: XCTestCase { func testThenThrowsError() { enum TestError: Error { case fail } let expectation = self.expectation(description: "Then throws error") - let promise = ServicePromise.resolve(1) + let promise = DFPromise.resolve(1) promise.then { _ in throw TestError.fail }.catch { error in @@ -126,7 +125,7 @@ final class ServicePromiseTests: XCTestCase { func testMultipleThenHandlers() { let expectation1 = self.expectation(description: "First then called") let expectation2 = self.expectation(description: "Second then called") - let promise = ServicePromise.resolve("multi") + let promise = DFPromise.resolve("multi") promise.then { value in XCTAssertEqual(value, "multi") expectation1.fulfill() @@ -142,7 +141,7 @@ final class ServicePromiseTests: XCTestCase { enum TestError: Error { case fail } let expectation1 = self.expectation(description: "First catch called") let expectation2 = self.expectation(description: "Second catch called") - let promise = ServicePromise.reject(TestError.fail) + let promise = DFPromise.reject(TestError.fail) promise.catch { error in XCTAssertTrue(error is TestError) expectation1.fulfill() @@ -155,7 +154,7 @@ final class ServicePromiseTests: XCTestCase { } func testPromiseResolvesSuccessfully() { let expectation = self.expectation(description: "Promise should resolve") - let promise = ServicePromise { resolve, _ in + let promise = DFPromise { resolve, _ in DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) { resolve(42) } @@ -170,7 +169,7 @@ final class ServicePromiseTests: XCTestCase { func testPromiseRejectsWithError() { enum TestError: Error { case fail } let expectation = self.expectation(description: "Promise should reject") - let promise = ServicePromise { _, reject in + let promise = DFPromise { _, reject in DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) { reject(TestError.fail) } @@ -184,7 +183,7 @@ final class ServicePromiseTests: XCTestCase { func testThenChaining() { let expectation = self.expectation(description: "Promise chain should resolve") - let promise = ServicePromise { resolve, _ in + let promise = DFPromise { resolve, _ in resolve(10) } promise @@ -199,8 +198,8 @@ final class ServicePromiseTests: XCTestCase { XCTAssertEqual(value, "Final value: 20") return "20" } - .then { value -> ServicePromise in - return ServicePromise { resolve, _ in + .then { value -> DFPromise in + return DFPromise { resolve, _ in resolve("Chained value: \(value)") } }.then { value in @@ -213,7 +212,7 @@ final class ServicePromiseTests: XCTestCase { func testCatchAfterThen() { enum TestError: Error { case fail } let expectation = self.expectation(description: "Promise should catch error after then") - let promise = ServicePromise { _, reject in + let promise = DFPromise { _, reject in reject(TestError.fail) } promise @@ -229,7 +228,7 @@ final class ServicePromiseTests: XCTestCase { func testFinallyCalledOnFulfill() { let expectation = self.expectation(description: "Finally should be called on fulfill") - let promise = ServicePromise { resolve, _ in + let promise = DFPromise { resolve, _ in resolve("done") } promise.finally { @@ -241,7 +240,7 @@ final class ServicePromiseTests: XCTestCase { func testFinallyCalledOnReject() { enum TestError: Error { case fail } let expectation = self.expectation(description: "Finally should be called on reject") - let promise = ServicePromise { _, reject in + let promise = DFPromise { _, reject in reject(TestError.fail) } promise.finally { @@ -251,13 +250,13 @@ final class ServicePromiseTests: XCTestCase { } func testResolveWithValue() { - let promise = ServicePromise.resolve(100) + let promise = DFPromise.resolve(100) XCTAssertEqual(promise.value, 100) } func testRejectWithError() { enum TestError: Error { case fail } - let promise = ServicePromise.reject(TestError.fail) + let promise = DFPromise.reject(TestError.fail) XCTAssertNil(promise.value) XCTAssertTrue(!promise.isPending) @@ -265,11 +264,11 @@ final class ServicePromiseTests: XCTestCase { func testAllAndOrder() { let expectation = self.expectation(description: "All resolves in order") - let p1 = ServicePromise.resolve(1) - let p2 = ServicePromise.resolve(2) - let p3 = ServicePromise.resolve(3) + let p1 = DFPromise.resolve(1) + let p2 = DFPromise.resolve(2) + let p3 = DFPromise.resolve(3) - ServicePromise.all([p1, p2, p3]).then { values in + DFPromise.all([p1, p2, p3]).then { values in XCTAssertEqual(values, [1, 2, 3]) expectation.fulfill() } @@ -278,23 +277,23 @@ final class ServicePromiseTests: XCTestCase { } func testAllAsyncAndOrder() { let expectation = self.expectation(description: "All resolves in order with async") - let p1 = ServicePromise { resolve, _ in + let p1 = DFPromise { resolve, _ in DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) { resolve(1) } } - let p2 = ServicePromise { resolve, _ in + let p2 = DFPromise { resolve, _ in DispatchQueue.global().asyncAfter(deadline: .now() + 0.2) { resolve(2) } } - let p3 = ServicePromise { resolve, _ in + let p3 = DFPromise { resolve, _ in DispatchQueue.global().asyncAfter(deadline: .now() + 0.3) { resolve(3) } } - ServicePromise.all([p1, p2, p3]).then { values in + DFPromise.all([p1, p2, p3]).then { values in XCTAssertEqual(values, [1, 2, 3]) expectation.fulfill() } @@ -304,7 +303,7 @@ final class ServicePromiseTests: XCTestCase { @available(macOS 10.15, iOS 13.0, *) func testAsyncInitAndWait() async throws { - let promise = ServicePromise { + let promise = DFPromise { try await Task.sleep(nanoseconds: 100_000_000) return 99 }