Home > Software design >  Saving string in flatMap block to database in api call using Combine Swift
Saving string in flatMap block to database in api call using Combine Swift

Time:10-05

I am trying to fetch a value from local database and when not found wants to save it to local database and return it. All of these I am doing in Interactor file and actual saving or fetching is done in seperate file. Following is my code:

public func fetchCode(codeId: String) -> AnyPublisher<String?, Error> {
    //Get code from localdb
    codeStorageProvider.fetchCode(codeId).flatMap { (code) -> AnyPublisher<String?, Error> in
        if let code = code {
            return Just(code).mapError{ $0 as Error }.eraseToAnyPublisher()
        }
        //If not found in db, Get code from server
        let code = self.voucherCodeProvider.fetchVoucherCode(codeId: codeId)
        return code.flatMap { code in
            //save the code to local db
            self.codeStorageProvider.saveVoucherCode(code, codeId)
            return code
        }.eraseToAnyPublisher()
        //return code to presenter
    }.eraseToAnyPublisher()
}

I am getting following error in flatMap:

Type of expression is ambiguous without more context

Can someone please help me?

CodePudding user response:

If your saveVoucher doesn't return a Publisher and you are not interested in knowing when the operation is completed, there's no need to use flatMap but you can use handleEvents and call the side effect to save the code from there. Something like this:

func fetchLocal(codeId: String) -> AnyPublisher<String?, Error> {
  return Empty().eraseToAnyPublisher()
}

func fetchRemote(codeId: String) -> AnyPublisher<String, Error> {
  return Empty().eraseToAnyPublisher()
}

func saveLocal(code: String, codeId: String) {
  // Save to BD
}

func fetch(codeId: String) -> AnyPublisher<String?, Error> {
  return fetchLocal(codeId: codeId)
    .flatMap { code -> AnyPublisher<String, Error> in
      if let code = code {
        return Just(code)
          .setFailureType(to: Error.self)
          .eraseToAnyPublisher()
      } else {
        return fetchRemote(codeId: codeId)
          .handleEvents(receiveOutput: {
            saveLocal(code: $0, codeId: codeId)
          })
          .eraseToAnyPublisher()
      }
    }
    .map(Optional.some)
    .eraseToAnyPublisher()
}
  • Related