투케이2K

196. (swift5/xcode) [RxSwift] [Observable] http 요청 수행 후 error 에러 발생 시 retry 재요청 수행 실시 본문

Swift

196. (swift5/xcode) [RxSwift] [Observable] http 요청 수행 후 error 에러 발생 시 retry 재요청 수행 실시

투케이2K 2023. 12. 10. 19:06

[개발 환경 설정]

개발 툴 : XCODE

개발 언어 : SWIFT5

 

[소스 코드]

    // -----------------------------------------------------------------------------------------
    // MARK: - [테스트 메인 함수 정의 실시]
    // -----------------------------------------------------------------------------------------
    func testMain() {
        S_Log._D_(description: "테스트 함수 시작 실시", data: nil)
        
        
        /*
         ------------------------------------
         [요약 설명]
         ------------------------------------
         1. 반응형 프로그래밍 은 데이터의 흐름을 먼저 정의하고, 데이터가 변경되었을 때 [연관된 작업] 을 수행합니다
         ------------------------------------
         2. ReactiveX 는 Observer Pattern 옵저버 패턴 을 확장하며, Sequence 를 조합할 수 있는 연산자를 지원하며,
         low-level Thread, 동기화, Thread 안전성, non-blocking I/O에 관한 우려를 줄입니다
         ------------------------------------
         3. 필요 import :
         
         import RxSwift
         ------------------------------------
         4. 라이브러리 설치 참고 사이트 :
         
         https://blog.naver.com/kkh0977/223268744402
         https://github.com/ReactiveX/RxSwift
         ------------------------------------
         */
        
        
        // [로직 처리 실시]
        DispatchQueue.main.async {
            
            
            // [재시도 변수 선언]
            let maxRetryCount = 3

            
            // [Observable 생성]
            let subscription = self.observableCreate()
                .retry { error in
                    error.enumerated().flatMap { (tryCount, error) -> Observable<Int> in
                        if (tryCount + 1) > maxRetryCount {
                            
                            S_Log._D_(description: "observable :: retryWhen :: End", data: nil)
                            
                            return Observable.error(error)
                        }
                        
                        S_Log._D_(description: "observable :: retryWhen", data: ["\((tryCount + 1))"])
                        
                        return Observable<Int>.timer(.seconds(5), scheduler: MainScheduler.instance).take(1)
                        
                    }
                }
                .subscribe(
                    onNext: { element in // [발행 아이템 요소]
                        
                        S_Log._D_(description: "observable :: onNext :: ", data: ["\(element)"])
                    
                    }
                ) { onError in // [발행 에러]
                    
                    S_Log._D_(description: "observable :: onError", data: ["\(onError)"])
                    
                } onCompleted: { // [발행 완료]
                    
                    S_Log._D_(description: "observable :: onCompleted", data: nil)
                    
                } onDisposed: { // [구독 연결 및 해제]
                    
                    S_Log._D_(description: "observable :: onDisposed", data: nil)
                    
                }


        }


    }
    
    
    
    
    
    // -----------------------------------------------------------------------------------------
    // MARK: - [Observable.create 리턴 함수 선언]
    // -----------------------------------------------------------------------------------------
    func observableCreate() -> Observable<String> {
        S_Log._D_(description: "observableCreate 함수 시작 실시", data: nil)
        
        return Observable<String>.create { observer in
            
            // [로직 처리 실시]
            DispatchQueue.main.async {
                
                
                // -----------------------------------------
                // [URLRequest 생성 실시]
                // -----------------------------------------
                let urlComponents = URLComponents(string: "http://error")
                var requestURL = URLRequest(url: (urlComponents?.url)!)
                
                requestURL.httpMethod = "GET"
                
                requestURL.addValue("application/x-www-form-urlencoded; charset=utf-8;", forHTTPHeaderField: "Content-Type") // header settings
                requestURL.addValue("no-cache", forHTTPHeaderField: "Cache-Control") // header settings
                
                
                // -----------------------------------------
                // [http 요쳥을 위한 URLSessionDataTask 생성]
                // -----------------------------------------
                let sessionConfig = URLSessionConfiguration.default
                sessionConfig.timeoutIntervalForRequest = 15 // [커넥션 타임 아웃 설정]
                sessionConfig.timeoutIntervalForResource = 15 // [리소스 읽기 , 쓰기]
                
                let session = URLSession(configuration: sessionConfig)
                
                let dataTask = session.dataTask(with: requestURL, completionHandler: { (data, response, error) in

                    // [error가 존재하면 종료]
                    guard error == nil else {
                        observer.onError(NSError(domain: "observable.error", code: 0, userInfo: [NSLocalizedDescriptionKey: "ResponseError : \(error?.localizedDescription ?? "")"]))
                        observer.onCompleted()
                        return
                    }

                    
                    // [status 코드 체크 실시]
                    let successsRange = 200..<300
                    guard let statusCode = (response as? HTTPURLResponse)?.statusCode, successsRange.contains(statusCode)
                    else {
                        observer.onError(NSError(domain: "observable.error", code: 0, userInfo: [NSLocalizedDescriptionKey: "ResponseCodeError : \(String(describing: (response as? HTTPURLResponse)?.statusCode ?? 0))"]))
                        observer.onCompleted()
                        return
                    }

                    
                    // [response 데이터 획득]
                    let resultCode = (response as? HTTPURLResponse)?.statusCode ?? 0 // [상태 코드]
                    let resultData = String(data: data!, encoding: .utf8) ?? "" // [데이터 확인]
                    
                    
                    // [콜백 반환]
                    observer.onNext("\(resultData)")
                    observer.onCompleted()
                })

                
                // [network 통신 실행]
                dataTask.resume()
                
            }
            return Disposables.create()
            
        }

    }
 

[결과 출력]


 

반응형
Comments