# interval

설정한 시간 주기에 맞춰 1씩 증가하는 정수를 이벤트로 방출하는 연산자이다.

let i = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)

let subscription1 = i.subscribe { print("1 >> \($0)")} // next(0), next(1) ...

DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
    subscription1.dispose() // 5초 뒤 dispose
}

인터벌 연산자는 타이머가 발동되는 시점이 옵저버블을 생성한 때가 아닌 구독자가 구독한 시점부터 이루어진다.

let i = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)

var subscription2: Disposable? // 구독작 Disposable타입으로 선언

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    subscription2 = i.subscribe{ print("2 >> \($0)") } // 2초 뒤 구독
}

DispatchQueue.main.asyncAfter(deadline: .now() + 7){
    subscription2?.dispose() // 2~7초까지 이벤트 방출
}

# timer

타이머 연산자는 이벤트 전달 시점과 이벤트 방출 주기를 직접 설정할 수 있는 연산자이다.

  1. _ duetime: dueTime에 전달된 시점 이후에 첫 이벤트가 전달된다.
  2. period: RxTimeInterval? = nil: 이벤트 방출 주기를 설정한다. nil인 경우 이벤트를 하나만 방출하고 끝낸다.
  3. scheduler: 스케줄러를 지정한다.
var bag = DisposeBag()
let subscription = Observable<Int>.timer(.seconds(1), period: .seconds(1), scheduler: MainScheduler.instance)
    .subscribe{ print($0) }

DispatchQueue.main.asyncAfter(deadline: .now() + 5){
    subscription.disposed(by: bag)
    bag = DisposeBag()
}
  1. 1초 뒤에 정수를 이벤트로 방출한다.
  2. 이후 1초마다 정수를 계속해서 방출한다.
  3. 5초 뒤 DisposeBag을 초기화하여 내부 옵저버블을 종료한다.

# timeout

타임아웃 연산자는 지정된 시간 내에 소스 옵저버블에서 이벤트가 방출되지 않는 경우 에러를 방출한다.

let bag = DisposeBag()

// 소스 옵저버블
let subject = PublishSubject<Int>()

subject.timeout(.seconds(3), scheduler: MainScheduler.instance)
    .subscribe{ print($0) }
    .disposed(by: bag)

// .timer(.seconds(4), ...) -> Error
Observable<Int>.timer(.seconds(0), period: .seconds(1), scheduler: MainScheduler.instance)
    .subscribe{ subject.onNext($0) }
    .disposed(by: bag)
  1. 3초 타임아웃을 지정하고 구독해둔다.
  2. 새로운 옵저버블에서 타이머 연산자를 통해 1초마다 정수를 소스 옵저버블로 방출한다.
  3. 매 초마다 정수가 정상적으로 전달되므로 소스 옵저버블인 서브젝트는 에러를 반환하지 않는다.
  4. 타이머 연산자의 dueTime 파라미터값을 3초보다 더 큰값을 지정하면 서브젝트에서 에러를 방출한다.

또한 타임아웃에는 other 파라미터도 지정할 수 있다. 타임아웃 기한까지 이벤트 방출이 이루어지지 않을 경우 대체할 옵저버블을 전달한다.

// other에 정수 0만 전달하는 옵저버블 지정
subject.timeout(.seconds(3), other: Observable.just(0) , scheduler: MainScheduler.instance)
    .subscribe{ print($0) }
    .disposed(by: bag)

Observable<Int>.timer(.seconds(4), period: .seconds(1), scheduler: MainScheduler.instance)
    .subscribe{ subject.onNext($0) }
    .disposed(by: bag)

# delay, delaySubscription

딜레이 연산자는 이벤트 방출 후 구독자로 전달되는 시점을 딜레이시킨다. 구독시점 및 이벤트 방출 시점 자체를 딜레이시키는 것이 아니다.

Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
    .take(5)
    .delay(.seconds(5), scheduler: MainScheduler.instance)
    .subscribe{ print($0) }
    .disposed(by: bag)
  1. 1초마다 정수를 방출하는 인터벌 연산자를 사용한다.
  2. take 연산자를 통해 5개의 이벤트를 취한다.
  3. 차례로 방출되는 5개의 이벤트들을 각각 5초 뒤에 구독자에게 전달한다. (이벤트 방출은 이루어진 상태이다.)

반면 delaySubscription 연산자는 구독 시점 자체를 지연시킨다.

Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
    .take(5)
    .debug()
    .delaySubscription(.seconds(5), scheduler: MainScheduler.instance)
    .subscribe{ print($0) }
    .disposed(by: bag)

디버그 연산자를 사용하면 코드 흐름을 쉽게 파악할 수 있다.

  1. 정수 이벤트 5개를 받는다.
  2. 구독시점을 5초 뒤로 딜레이시켰으므로, 5초동안 아무것도 출력되지 않는다.