Search code examples
iosswiftpromisekit

Cannot get data in handler for when(resolved:)


PromiseKit 6

I have a function that fetches a list of alerts from a db, I then need to use the contentId property on each to fetch the content and attach to the appropriate alert item.

Maybe there's a better way, but for now, what I came up with is to collect the promises into a list and call when(resolved:). I chose that because if any promise fails, I want to be able to return all those that can pass.

Inside my then handler in the function attachContents, the handler gets passed this type [Result] but the only field I can access when I map the list is isFulfilled I checked what type Result was and found this:

public enum Result<T> {
    case fulfilled(T)
    case rejected(Error)
}

public extension PromiseKit.Result {
    var isFulfilled: Bool {
        switch self {
        case .fulfilled:
            return true
        case .rejected:
            return false
        }
    }
}

It led me to the first one, in Resolver.swift so I'm not sure why I can't get the data by calling fulfilled

private func getContent(for alert: Model) -> Promise<ViewModel> {
  return firstly { () -> Promise<Any> in

    if let contentType = AlertContentType(rawValue: alert.type) {
      switch contentType {
      case .news:
        return newsService.get(contentId: contentId, superareaId: superareaId).compactMap { $0 as Any }

      case .insight:
        return insightService.get(contentId: contentId, superareaId: superareaId).compactMap { $0 as Any }
      }
    } else { throw DataError.Missing(error: "Could not retrieve type!") }
  }.compactMap { content in
    var viewModel = alert.toViewModel()
    viewModel.content = content

    return viewModel
  }
}

private func attachContents(to alerts: [Model]) -> Promise<[ViewModel]> {
  return firstly { () -> Guarantee<[Result<ViewModel>]> in
    let contentPromises: [Promise<AlertViewModel>] = alerts.map {
      return self.getContent(for: $0)
    }
    return when(resolved: contentPromises)
  }.then { (vModels: [Result<ViewModel>]) -> Promise<[OIAlertViewModel]> in
    vModels.map { (vm: Result<OIAlertViewModel>) in
      // vm.isFulfilled is the only accessible property here
      // can't call 
    }
  }
}

Solution

  • Result is an enum of .fulfilled or .rejected

    vModels.map { (vm: Result<OIAlertViewModel>) in
        switch vm {
            case .fulfilled(let alert):
                print(alert)
            case .rejected(let error):
                print(error)
        }
    }