当用closure/resolver初始化一个promise时,我们可以直接抛出吗?

When initializing a promise with a closure/resolver, can we throw directly?

PromiseKit 具有 Promise:

的初始值设定项
/// Initialize a new promise that can be resolved with the provided `Resolver`.
public init(resolver body: (PromiseKit.Resolver<T>) throws -> Void)

有时我需要我的函数 return a Promise 但该函数的 return 值取决于其他抛出函数。自 resolver 闭包抛出后,在没有 do/catch 块的情况下直接调用 try 是否有效?或者我必须将每个抛出函数包装在 docatch 调用中 seal.reject(error)?

我更愿意直接使用 try,因为它比 return 没有 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)
    }
  }

在 Promise 中有抛出函数并且不在 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 会在内部处理,请查看 here 供您参考。