在Swift中,多次调用闭包是否正确?

4
我正在设计一个Swift API,在其中定义了一个名为EventTransmitter的协议,其中包含一个传输一批Events的方法。处理一批Events可能会以成功和失败的事件列表结束。
因此,该协议的任何实现都应该调用完成处理程序,并返回失败的事件和/或成功的事件。
public enum EventResult {

    /// When the event was transmitted correctly.
    case success([Event])

    /// When the event failed and should be discarded
    case failure([Event])
}

public protocol EventTransmitter {

    func transmit(events: [Event], completion: @escaping (EventResult) -> Void)
}

在上述协议中,实现该协议的人必须调用两次完成处理程序:

public class HTTPTransmitter: EventTransmitter {

    public func transmit(events: [Event], completion: @escaping (EventResult) -> Void) {

        let failedEvents =  ...
        let successEvents = ...

        completion(.failure(failedEvents))

        completion(.success(successEvents))
    }
}

使用方法如下

transmitter.transmit(events: events, completion: { result in
    switch result {
    case .success(let events):
        // handle success events
    case .failure(let events):
        // handle failed events
    }
})

需要要求多次调用一个完成闭包吗?

还是为每种情况设置不同的闭包更合适:

public protocol EventTransmitter {

    typealias EventCallback = (([Event]) -> Void)

    func transmit(events: [Event], onSuccess: @escaping EventCallback, onFailure: @escaping EventCallback)
}
1个回答

3

如果你想做类似这样的事情,其中包括失败事件和成功事件的列表,那么我可能会将它们合并到同一个回调函数中...

一个类似以下的回调函数...

typealias EventCallBack = (succeeded: [Event], failed: [Event]) -> ()

然后您只需要调用回调函数一次。
如果你有一个枚举来捕获回调的状态,那么我建议只运行一次。
这纯粹是从 API 的角度来看的。什么意思呢?处理两次成功怎么办?三次?或者一个成功和一个失败相比,再失败再成功等等……
当然,你可以多次调用它,并且有些情况下你可能想这样做。例如,存储一个闭包并在响应用户交互或其他事件时调用它。
但对于像这样只有一个请求的情况,我建议使用所有必要信息调用它一次。
另一种可能的选择是将 success 和 failure 的闭包处理整合到 Event 中。
这样,如果一个事件失败了,你可以调用 event.failed(),如果成功…event.succeeded() 或者类似的方法。
我不知道在这种特定情况下这是否是一个好主意,但它肯定是另一个选项:D
您还可以定义枚举,如……
enum EventResult {
    case success(Event)
    case failed(Event)
}

然后将您的回调函数编写为以下形式...

([EventResult]) -> ()

那么,您只需使用一个包含所有单独结果的数组一次调用即可。如果结果的顺序与事件的顺序相同很重要,那么这将非常有用。

1
没错,我没有考虑到有人可能会调用“succeeded”两次的情况 :) 因此,你提出的一个回调函数带有多个参数的建议似乎更好。谢谢! - Jan
1
另一种方法是让 EventResult 封装单个事件的结果,并使闭包接受 [EventResult]。 如果原始事件的顺序对回调接收方很重要,则可能会更喜欢这种方法。 - vacawama
1
@vacawama 的确。这样你就可以得到与你传入的事件数量相同的结果数。并且可以看到每个事件是成功还是失败。 - Fogmeister
@vacawama 谢谢,从 API 设计的角度来看,这更加清晰了。 - Jan
1
很棒的回答@Fogmeister(我点赞了)。你的回答提供了几种不错的替代实现。 - vacawama
如何使用它?你能再解释一下吗? - Niib Fouda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接