У меня есть сторонний SDK, где архитектура выглядит следующим образом:
- Я вызываю метод службы (давайте назовем его
TheirService
) - Как только этот метод завершитсяделегат этой службы (давайте позвоним
TheirServiceDelegate
получит уведомление onSuccess
в случае успешного вызова или onFailure
в случае сбоя.
Проблема в том, что методы TheirService
зависят друг от друга, поэтому я в конечном итоге получаю «цепную реакцию», при которой каждый следующий метод TheirService
вызывается из предыдущего обратного вызова.
Обратите внимание, что TheirService
является однопоточным и действительноПривыкну, чтобы предыдущий метод был завершен до того, как я смогу запустить следующий.
В настоящее время мои взаимодействия со службой выглядят так:
protocol MyClientListener {
notifyOnFailure()
notifyOnResult(result: SomeObject)
}
class MyClient: TheirServiceDelegate {
static let instance = MyClient()
let myService = TheirService()
var myResult: SomeObject?
var resultListener: MyClientListener
private init() { }
func start(resultListener: MyClientListener) {
self.resultListener = resultListener
myService.initialize()
}
// TheirServiceDelegate method
func onInitializeSuccess() {
myService.bootstrap()
}
// TheirServiceDelegate method
func onBootstrapSuccess() {
myService.login(user, password)
}
// TheirServiceDelegate method
func onLoginSuccess() {
myService.doSomethingUsefulStep1()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep1Success() {
myService.doSomethingUsefulStep2()
}
// TheirServiceDelegate method
func onDoSomethingUsefulStep2Success(result: SomeObject) {
// ah, look, now I have some object I actually wanted!
resultListener.notifyOnResult(result)
}
}
Мне также приходится иметь дело со случаем сбоя для каждогоиз них. И я не могу пропустить или изменить порядок шагов, что создает какой-то неуклюжий конечный автомат.
Вместо этого я хотел бы взаимодействовать со службой через логические функции, которые завершают определенные этапыпроцесс от начала до конца, ожидая результатов между шагами:
class MyClient {
static let instance = MyClient()
let myService = MyService()
private init() { }
func connect() throws {
myService.initialize()
// wait for success or failure, throw on failure
myService.bootstrap()
// wait for success or failure, throw on failure
myService.login(user, password)
// wait for success or failure, throw on failure
}
func doSomethingUseful() -> SomeObject {
myService.doSomethingUsefulStep1()
// wait for success or failure, throw on failure
myService.doSomethingUsefulStep2()
// wait for success or failure, throw on failure
// on success, it will get an object it could return
}
Вызывается так:
try MyClient.instance.connect()
let x = try MyClient.instance.doSomethingUseful()
Так есть ли способ превратить комментарий «ждать успеха или неудачи»в реальный код, который ждет, чтобы этот однопоточный сервис перезвонил?И куда в таком случае поместится делегат?