shareReplay, ReplayValue & CompletionValue

기억하는 멀티캐스트: 유계 재생 버퍼, 닫힐 때의 마지막 값, 그리고 소스를 둘 다로 감싸는 체인 연산자.

class ReplayValue<T> { ReplayValue({int? size = 1, Duration? maxAge}); void add(T value); FxEvents<T> get live; // buffer, then live updates Future<void> close(); } class CompletionValue<T> { CompletionValue(); void add(T value); // remembered, emitted on close FxEvents<T> get live; Future<void> close(); } ConnectableEvents<T> FxEvents<T>.connectable() FxEvents<T> ConnectableEvents<T>.refCount() FxEvents<T> FxEvents<T>.shareReplay({int? size, Duration? maxAge, bool resetOnCancel = true})

강의

share는 한 번의 실행을 여러 리스너에게 방송한 뒤 잊습니다. 이벤트가 지나간 뒤에 도착한 리스너는 놓친 것입니다. ReplayValue는 기억하는 서브젝트입니다: addsize(기본값 1, null은 무한)와 maxAge로 잘린 버퍼에 덧붙이고, 모든 늦은 구독자는 보관된 버퍼를 먼저 재생받은 다음 라이브 갱신에 올라탑니다. 에러는 보관되지 않습니다. close 뒤에도 늦은 리스너는 버퍼를 받은 다음 종료됩니다. fxdart 이벤트 레이어, Rx의 ReplaySubject를 따랐습니다.

CompletionValue는 다른 기억입니다: add는 기억만 하고, 마지막 값은 닫힐 때 나옵니다 — 열려 있는 동안은 아무것도, 그다음 그 값과 종료. 닫힌 뒤의 늦은 리스너도 같습니다. addError는 기억된 값이 아니라 에러로 즉시 완료합니다. Rx의 AsyncSubject입니다. 다음 쪽의 LiveValue는 동기 .value 읽기를 가진 현재-값 서브젝트입니다 — getter가 없는 size 1의 ReplayValue입니다.

connectable()은 수동 형태입니다: ConnectableEvents를 돌려주고, 그 events 피드는 connect() 전까지 소스를 구독하지 않습니다. 그 전에 붙인 리스너는 기다리고, 늦은 리스너는 이미 나간 값을 놓칩니다. refCount()는 첫 리스너에서 연결하고 마지막에서 끊으며, 소스가 두 번째 리슨을 허용하면 다시 연결합니다. shareReplay가 흔한 표기입니다: ReplayValue를 통한 멀티캐스트, 첫 리스너에서 연결, 늦은 리스너는 이력을 봅니다. resetOnCancel(기본값 true)는 마지막 리스너가 떠나면 새 버퍼를 시작하고, false는 소스를 영영 연결해 둡니다.

fxdart 이벤트 레이어, Rx의 ReplaySubject, AsyncSubject, ConnectableObservable, 그리고 shareReplay를 따랐습니다.

데모 1 · 늦은 구독자가 버퍼를 본다

데모 2 · CompletionValue는 닫힐 때 내보낸다

직접 해 보기

연습: fromIterable 위의 shareReplay, 리스너 둘.

관련 항목: share — 기억 없는 멀티캐스트; 늦은 리스너는 이미 지나간 것을 놓침 · LiveValue — 동기 .value를 가진 현재-값 서브젝트 · fxEvents — 이 서브젝트들의 .live가 그 체인