При инициализации обещания с закрытием / распознавателем, мы можем бросить напрямую?
У PromiseKit есть этот инициализатор для Promise
:
/// Initialize a new promise that can be resolved with the provided `Resolver`.
public init(resolver body: (PromiseKit.Resolver<T>) throws -> Void)
Иногда мне нужна моя функция, чтобы вернуть Promise
но возвращаемое значение этой функции зависит от других бросающих функций. Это действительно, чтобы позвонить try
прямо без do/catch
блок с resolver
закрытие бросает? Или я должен обернуть каждую функцию броска в do
и в catch
вызов seal.reject(error)
?
Я бы предпочел использовать напрямую try
потому что гораздо чище вернуть конечный результат без do/catch
,
Эта проблема кажется актуальной, но я хотел бы получить подтверждение этих подходов, поскольку она не упоминается в документации: https://github.com/mxcl/PromiseKit/issues/799.
Это действительно?
private func getCNContacts() -> Promise<[CNContact]> {
return Promise { seal in
let fullNameKeyDescriptor = CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
guard let keysToFetch = [fullNameKeyDescriptor, CNContactPhoneNumbersKey] as? [CNKeyDescriptor] else {
throw CKPersistenceError.failedToFetch("Could not cast as [CNKeyDescriptor]")
}
var results: [CNContact] = []
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
try contactStore.enumerateContacts(with: fetchRequest) { contact, _ in
results.append(contact)
}
seal.fulfill(results)
}
}
Или я должен использовать do/catch
как это:
private func getCNContacts() -> Promise<[CNContact]> {
return Promise { seal in
let fullNameKeyDescriptor = CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
guard let keysToFetch = [fullNameKeyDescriptor, CNContactPhoneNumbersKey] as? [CNKeyDescriptor] else {
seal.reject(CKPersistenceError.failedToFetch("Could not cast as [CNKeyDescriptor]"))
return
}
do {
var results: [CNContact] = []
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
try contactStore.enumerateContacts(with: fetchRequest) { contact, _ in
results.append(contact)
}
seal.fulfill(results)
} catch {
seal.reject(error)
}
}
}
Также есть такая возможность, но я думаю, что это может иметь последствия для потоков:
private func getCNContacts() -> Promise<[CNContact]> {
let fullNameKeyDescriptor = CNContactFormatter.descriptorForRequiredKeys(for: .fullName)
guard let keysToFetch = [fullNameKeyDescriptor, CNContactPhoneNumbersKey] as? [CNKeyDescriptor] else {
let error = CKPersistenceError.failedToFetch("Could not cast as [CNKeyDescriptor]")
return Promise(error: error)
}
do {
var results: [CNContact] = []
let fetchRequest = CNContactFetchRequest(keysToFetch: keysToFetch)
try contactStore.enumerateContacts(with: fetchRequest) { contact, _ in
results.append(contact)
}
return Promise.value(results)
} catch {
return Promise(error: error)
}
}
1 ответ
Совершенно верно иметь функцию бросания внутри Promise и не обрабатывать ошибку в блоке разрешения обещаний.
Но, если вы хотите обработать ошибку, вы можете использовать catch(on: flags:, policy: , _ )
,
Вот небольшой эксперимент, который я сделал на основе вашего вопроса.
simplePromise = Promise { resolver in
let string = try self.getSomeString()
resolver.resolve(Result.fulfilled(string))
}
simplePromise.done { results in
print(results)
}.catch { error in
print("Error occurred: \(error)")
}
Теперь, если мой метод getSomeString()
бросает, код внутри catch
блок вызывается, но если он успешно разрешен, то код внутри done
называется.
Вы можете попробовать, создав метод getSomeString
и бросать оттуда так,
enum MyError: Error {
case sampleError
}
func getSomeString() throws -> String {
throw MyError.sampleError
}
И также попробовать, не бросая.
Таким образом, кажется, что обычный способ справиться с ошибкой бросания функции заключается в реализации catch
Перезвоните.
Вы также не можете реализовать catch, и ваш код не потерпит крах. В конце концов, метательные функции рассматриваются как sealed.reject
Кстати, если вы хотите, вы можете посмотреть на код. Вы не должны обрабатывать ошибку с do { } catch
но PromiseKit делает это внутренне, посмотрите здесь для вашей ссылки.