При инициализации обещания с закрытием / распознавателем, мы можем бросить напрямую?

У 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 делает это внутренне, посмотрите здесь для вашей ссылки.

Другие вопросы по тегам