Do.

Combine - 여러 요청 결과를 결합해야 하는 경우 본문

iOS

Combine - 여러 요청 결과를 결합해야 하는 경우

Hey_Hen 2022. 5. 17. 15:18

Issue

서버에서 A.Request의 요청 결과를 받고 A의 결과에 따라 B.Request를 수행해야 하는 상황

Combine으로는 이를 어떻게 처리를 해야 할까 고민했습니다.

 

    A_Request.sink { _ in
      
    } receiveValue: { data in
      
      //processing
      
      B_Request.sink { _ in
        
      } receiveValue: { data2 in
        //processing + data2 processing
      }
    }

무식한 방법으로는 위와 같이, A_Request를 받고 내부에서 B_Request를 또 호출하는 방법이지만, 괜찮은 코드는 아닙니다. 코드 자체가 불필요한 뎁스를 가지기도 하고 가독성도 떨어지며, 두 기능을 분리하기가 쉽지 않네요.

Solution

소개 드릴 기능은 CombineLastest로 Rx를 많이들 써보셨다면 잘 아시는 결합 오퍼레이터입니다.

다양한 결합 연산자 중에 CombineLastest를 써야 하는 이유가 있는데요

 

다른 결합 연산자는 각 퍼블리셔의 스트림을 합쳐주는 역할을 하기는 하지만, 기존 데이터를 받고, 그거에 대해서 또 처리를 하기는 용이 하지 않습니다.

Merge, Append, Prepend등은 위와 같은 도식 형태로 Publisher를 결합하는 반면(오퍼레이터 마다 조금 다릅니다.)

 

 

CombineLastest는 퍼블리셔를 결합에 튜플로 뱉습니다.

A_Request.combineLatest(B_Request)
      .sink(receiveCompletion: { _ in }
        receiveValue: { (a, b) in
        let c = C(a: a, b: b)
        print(c)
      })

 

CombineLastest는 또 좋은점이 순서를 보장 해준다는 것인데요

      Timer.publish(every: 3.0, on: .main, in: .common)
        .autoconnect()
        .sink { [unowned self] _ in
          DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            self.publisher2.send("7")
          }
          DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            self.publisher1.send("5")
          }

        }
        .store(in: &subscriptions)

위 코드 처럼 명백하게 publisher2에 값이 먼저 도착하고 publisher1에 값이 도착을 해도 결과물은

 

5다음 7이 들어오게 됩니다.

이 부분은 처음에 combineLastest를 할 때 publisher1뒤에 publisher2를 결합했기 때문입니다. 만약 순서를 바꾸고 싶다면, 결합하는 코드를 바꾸면 되겠죠.

 

이상 즐거운 컴바인이었습니다.

Comments