Skip to content
This repository was archived by the owner on Sep 6, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ struct CounterState: ServiceStateType {
```


### 实现ServicePromise 异步使用
### 实现DFPromise 异步使用

`ServicePromise` 提供了基于 Promise 的异步服务调用方式,适合需要链式调用或异步返回结果的场景。
`DFPromise` 提供了基于 Promise 的异步服务调用方式,适合需要链式调用或异步返回结果的场景。

#### 示例:异步获取数据

Expand All @@ -70,7 +70,7 @@ struct UserInfo: Codable {
}

// 定义一个 ServicePromise
let promise = ServicePromise<UserInfo> { resolver in
let promise = DFPromise<UserInfo> { resolver in
// 模拟异步网络请求
Task {
try await Task.sleep(nanoseconds: 1_000_000_000) // 1秒延迟
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
public final class ServicePromise<Value> {
public final class DFPromise<Value> {
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 被拒绝时调用
Expand Down Expand Up @@ -50,10 +45,10 @@ public final class ServicePromise<Value> {
}
}

extension ServicePromise {
extension DFPromise {
@discardableResult
public func then<U>(_ onFulfilled: @escaping (Value) throws -> U) -> ServicePromise<U> {
return ServicePromise<U> { resolve, reject in
public func then<U>(_ onFulfilled: @escaping (Value) throws -> U) -> DFPromise<U> {
return DFPromise<U> { resolve, reject in
let handle = { (value: Value) in
do {
let result = try onFulfilled(value)
Expand All @@ -80,9 +75,9 @@ extension ServicePromise {
}
@discardableResult
public func then<U>(
_ onFulfilled: @escaping (Value) throws -> ServicePromise<U>
) -> ServicePromise<U> {
return ServicePromise<U> { resolve, reject in
_ onFulfilled: @escaping (Value) throws -> DFPromise<U>
) -> DFPromise<U> {
return DFPromise<U> { resolve, reject in
let handle: (Value) -> Void = { value in
do {
let nextPromise = try onFulfilled(value)
Expand Down Expand Up @@ -138,11 +133,11 @@ extension ServicePromise {
}

//拓展Promise 常用函数 转换错误等
public static func all(_ promises: [ServicePromise<Value>]) -> ServicePromise<[Value]> {
public static func all(_ promises: [DFPromise<Value>]) -> 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

Expand All @@ -160,14 +155,14 @@ extension ServicePromise {
}
}

public static func resolve(_ value: Value) -> ServicePromise<Value> {
return ServicePromise<Value> { resolve, _ in
public static func resolve(_ value: Value) -> DFPromise<Value> {
return DFPromise<Value> { resolve, _ in
resolve(value)
}
}

public static func reject(_ error: Error) -> ServicePromise<Value> {
return ServicePromise<Value> { _, reject in
public static func reject(_ error: Error) -> DFPromise<Value> {
return DFPromise<Value> { _, reject in
reject(error)
}
}
Expand All @@ -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
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//
// ServicePromiseTests.swift
// DFService
//
// Created by yaochenfeng on 2025/6/7.
Expand All @@ -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<String> { resolve, _ in
let promise = DFPromise<String> { resolve, _ in
resolve("immediate")
}
promise.then { value in
Expand All @@ -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<Int> { _, reject in
let promise = DFPromise<Int> { _, reject in
reject(TestError.fail)
}
promise.catch { error in
Expand All @@ -38,7 +37,7 @@ final class ServicePromiseTests: XCTestCase {

func testThenAfterResolve() {
let expectation = self.expectation(description: "Then after resolve")
let promise = ServicePromise<Int>.resolve(5)
let promise = DFPromise<Int>.resolve(5)
promise.then { value in
XCTAssertEqual(value, 5)
expectation.fulfill()
Expand All @@ -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<Int>.reject(TestError.fail)
let promise = DFPromise<Int>.reject(TestError.fail)
promise.catch { error in
XCTAssertTrue(error is TestError)
expectation.fulfill()
Expand All @@ -59,7 +58,7 @@ final class ServicePromiseTests: XCTestCase {

func testFinallyAfterResolve() {
let expectation = self.expectation(description: "Finally after resolve")
let promise = ServicePromise<Int>.resolve(1)
let promise = DFPromise<Int>.resolve(1)
promise.finally {
expectation.fulfill()
}
Expand All @@ -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<Int>.reject(TestError.fail)
let promise = DFPromise<Int>.reject(TestError.fail)
promise.finally {
expectation.fulfill()
}
Expand All @@ -78,10 +77,10 @@ final class ServicePromiseTests: XCTestCase {

func testAllResolves() {
let expectation = self.expectation(description: "All resolves")
let p1 = ServicePromise<Int>.resolve(1)
let p2 = ServicePromise<Int>.resolve(2)
let p3 = ServicePromise<Int>.resolve(3)
ServicePromise.all([p1, p2, p3]).then { values in
let p1 = DFPromise<Int>.resolve(1)
let p2 = DFPromise<Int>.resolve(2)
let p3 = DFPromise<Int>.resolve(3)
DFPromise.all([p1, p2, p3]).then { values in
XCTAssertEqual(values.sorted(), [1, 2, 3])
expectation.fulfill()
}
Expand All @@ -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<Int>.resolve(1)
let p2 = ServicePromise<Int>.reject(TestError.fail)
let p3 = ServicePromise<Int>.resolve(3)
ServicePromise.all([p1, p2, p3]).catch { error in
let p1 = DFPromise<Int>.resolve(1)
let p2 = DFPromise<Int>.reject(TestError.fail)
let p3 = DFPromise<Int>.resolve(3)
DFPromise.all([p1, p2, p3]).catch { error in
XCTAssertTrue(error is TestError)
expectation.fulfill()
}
Expand All @@ -103,7 +102,7 @@ final class ServicePromiseTests: XCTestCase {

func testAllEmptyArray() {
let expectation = self.expectation(description: "All with empty array resolves immediately")
ServicePromise<Int>.all([]).then { values in
DFPromise<Int>.all([]).then { values in
XCTAssertEqual(values.count, 0)
expectation.fulfill()
}
Expand All @@ -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<Int>.resolve(1)
let promise = DFPromise<Int>.resolve(1)
promise.then { _ in
throw TestError.fail
}.catch { error in
Expand All @@ -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<String>.resolve("multi")
let promise = DFPromise<String>.resolve("multi")
promise.then { value in
XCTAssertEqual(value, "multi")
expectation1.fulfill()
Expand All @@ -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<String>.reject(TestError.fail)
let promise = DFPromise<String>.reject(TestError.fail)
promise.catch { error in
XCTAssertTrue(error is TestError)
expectation1.fulfill()
Expand All @@ -155,7 +154,7 @@ final class ServicePromiseTests: XCTestCase {
}
func testPromiseResolvesSuccessfully() {
let expectation = self.expectation(description: "Promise should resolve")
let promise = ServicePromise<Int> { resolve, _ in
let promise = DFPromise<Int> { resolve, _ in
DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) {
resolve(42)
}
Expand All @@ -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<Int> { _, reject in
let promise = DFPromise<Int> { _, reject in
DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) {
reject(TestError.fail)
}
Expand All @@ -184,7 +183,7 @@ final class ServicePromiseTests: XCTestCase {

func testThenChaining() {
let expectation = self.expectation(description: "Promise chain should resolve")
let promise = ServicePromise<Int> { resolve, _ in
let promise = DFPromise<Int> { resolve, _ in
resolve(10)
}
promise
Expand All @@ -199,8 +198,8 @@ final class ServicePromiseTests: XCTestCase {
XCTAssertEqual(value, "Final value: 20")
return "20"
}
.then { value -> ServicePromise<String> in
return ServicePromise<String> { resolve, _ in
.then { value -> DFPromise<String> in
return DFPromise<String> { resolve, _ in
resolve("Chained value: \(value)")
}
}.then { value in
Expand All @@ -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<Int> { _, reject in
let promise = DFPromise<Int> { _, reject in
reject(TestError.fail)
}
promise
Expand All @@ -229,7 +228,7 @@ final class ServicePromiseTests: XCTestCase {

func testFinallyCalledOnFulfill() {
let expectation = self.expectation(description: "Finally should be called on fulfill")
let promise = ServicePromise<String> { resolve, _ in
let promise = DFPromise<String> { resolve, _ in
resolve("done")
}
promise.finally {
Expand All @@ -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<String> { _, reject in
let promise = DFPromise<String> { _, reject in
reject(TestError.fail)
}
promise.finally {
Expand All @@ -251,25 +250,25 @@ final class ServicePromiseTests: XCTestCase {
}

func testResolveWithValue() {
let promise = ServicePromise<Int>.resolve(100)
let promise = DFPromise<Int>.resolve(100)

XCTAssertEqual(promise.value, 100)
}
func testRejectWithError() {
enum TestError: Error { case fail }
let promise = ServicePromise<Int>.reject(TestError.fail)
let promise = DFPromise<Int>.reject(TestError.fail)

XCTAssertNil(promise.value)
XCTAssertTrue(!promise.isPending)
}

func testAllAndOrder() {
let expectation = self.expectation(description: "All resolves in order")
let p1 = ServicePromise<Int>.resolve(1)
let p2 = ServicePromise<Int>.resolve(2)
let p3 = ServicePromise<Int>.resolve(3)
let p1 = DFPromise<Int>.resolve(1)
let p2 = DFPromise<Int>.resolve(2)
let p3 = DFPromise<Int>.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()
}
Expand All @@ -278,23 +277,23 @@ final class ServicePromiseTests: XCTestCase {
}
func testAllAsyncAndOrder() {
let expectation = self.expectation(description: "All resolves in order with async")
let p1 = ServicePromise<Int> { resolve, _ in
let p1 = DFPromise<Int> { resolve, _ in
DispatchQueue.global().asyncAfter(deadline: .now() + 0.1) {
resolve(1)
}
}
let p2 = ServicePromise<Int> { resolve, _ in
let p2 = DFPromise<Int> { resolve, _ in
DispatchQueue.global().asyncAfter(deadline: .now() + 0.2) {
resolve(2)
}
}
let p3 = ServicePromise<Int> { resolve, _ in
let p3 = DFPromise<Int> { 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()
}
Expand All @@ -304,7 +303,7 @@ final class ServicePromiseTests: XCTestCase {

@available(macOS 10.15, iOS 13.0, *)
func testAsyncInitAndWait() async throws {
let promise = ServicePromise<Int> {
let promise = DFPromise<Int> {
try await Task.sleep(nanoseconds: 100_000_000)
return 99
}
Expand Down