qiniu-js
Version:
Javascript SDK for Qiniu Resource (Cloud) Storage AP
152 lines (127 loc) • 4.26 kB
text/typescript
/** 消费者接口 */
export interface IObserver<T, E, C> {
/** 用来接收 Observable 中的 next 类型通知 */
next: (value: T) => void
/** 用来接收 Observable 中的 error 类型通知 */
error: (err: E) => void
/** 用来接收 Observable 中的 complete 类型通知 */
complete: (res: C) => void
}
export interface NextObserver<T, E, C> {
next: (value: T) => void
error?: (err: E) => void
complete?: (res: C) => void
}
export interface ErrorObserver<T, E, C> {
next?: (value: T) => void
error: (err: E) => void
complete?: (res: C) => void
}
export interface CompletionObserver<T, E, C> {
next?: (value: T) => void
error?: (err: E) => void
complete: (res: C) => void
}
export type PartialObserver<T, E, C> = NextObserver<T, E, C> | ErrorObserver<T, E, C> | CompletionObserver<T, E, C>
export interface IUnsubscribable {
/** 取消 observer 的订阅 */
unsubscribe(): void
}
/** Subscription 的接口 */
export interface ISubscriptionLike extends IUnsubscribable {
readonly closed: boolean
}
export type TeardownLogic = () => void
export interface ISubscribable<T, E, C> {
subscribe(
observer?: PartialObserver<T, E, C> | ((value: T) => void),
error?: (error: any) => void,
complete?: () => void
): IUnsubscribable
}
/** 表示可清理的资源,比如 Observable 的执行 */
class Subscription implements ISubscriptionLike {
/** 用来标示该 Subscription 是否被取消订阅的标示位 */
public closed = false
/** 清理 subscription 持有的资源 */
private _unsubscribe: TeardownLogic | undefined
/** 取消 observer 的订阅 */
unsubscribe() {
if (this.closed) {
return
}
this.closed = true
if (this._unsubscribe) {
this._unsubscribe()
}
}
/** 添加一个 tear down 在该 Subscription 的 unsubscribe() 期间调用 */
add(teardown: TeardownLogic) {
this._unsubscribe = teardown
}
}
/**
* 实现 Observer 接口并且继承 Subscription 类,Observer 是消费 Observable 值的公有 API
* 所有 Observers 都转化成了 Subscriber,以便提供类似 Subscription 的能力,比如 unsubscribe
*/
export class Subscriber<T, E, C> extends Subscription implements IObserver<T, E, C> {
protected isStopped = false
protected destination: Partial<IObserver<T, E, C>>
constructor(
observerOrNext?: PartialObserver<T, E, C> | ((value: T) => void) | null,
error?: ((err: E) => void) | null,
complete?: ((res: C) => void) | null
) {
super()
if (observerOrNext && typeof observerOrNext === 'object') {
this.destination = observerOrNext
} else {
this.destination = {
...observerOrNext && { next: observerOrNext },
...error && { error },
...complete && { complete }
}
}
}
unsubscribe(): void {
if (this.closed) {
return
}
this.isStopped = true
super.unsubscribe()
}
next(value: T) {
if (!this.isStopped && this.destination.next) {
this.destination.next(value)
}
}
error(err: E) {
if (!this.isStopped && this.destination.error) {
this.isStopped = true
this.destination.error(err)
}
}
complete(result: C) {
if (!this.isStopped && this.destination.complete) {
this.isStopped = true
this.destination.complete(result)
}
}
}
/** 可观察对象,当前的上传事件的集合 */
export class Observable<T, E, C> implements ISubscribable<T, E, C> {
constructor(private _subscribe: (subscriber: Subscriber<T, E, C>) => TeardownLogic) {}
subscribe(observer: PartialObserver<T, E, C>): Subscription
subscribe(next: null | undefined, error: null | undefined, complete: (res: C) => void): Subscription
subscribe(next: null | undefined, error: (error: E) => void, complete?: (res: C) => void): Subscription
subscribe(next: (value: T) => void, error: null | undefined, complete: (res: C) => void): Subscription
subscribe(
observerOrNext?: PartialObserver<T, E, C> | ((value: T) => void) | null,
error?: ((err: E) => void) | null,
complete?: ((res: C) => void) | null
): Subscription {
const sink = new Subscriber(observerOrNext, error, complete)
sink.add(this._subscribe(sink))
return sink
}
}