以下为ChatGPT自动生成的解答,正确与否请自行判断。 也许你也可以从大家的发帖中找到想要的答案!
BFE.devAI解答 - JavaScript 代码题
57. 实现Observable
实现一个基本的Observable,满足以下要求:
- 实现
Observable
构造函数,它应该接受一个参数subscribe
,这个参数是一个函数,这个函数接受一个observer
作为参数,这个observer
是一个对象,它有三个属性:next
、error
、complete
,这些属性都是函数。 next
函数会传递一个值给Observer
。error
函数会传递一个错误给Observer
。complete
函数表示Observable
结束,不再传递任何值给Observer
。- 当一个
Observer
通过调用subscribe
方法订阅Observable
时,subscribe
方法应该返回一个Subscription
对象。 Subscription
对象有一个unsubscribe
函数,当它被调用时,它会取消Observer
对Observable
的订阅,不再接收任何值。error
和complete
只能触发一次。其后的next/error/complete
需要被忽略。- 在订阅的时候
next/error/complete
需要都不是必须。如果传入的是一个函数,这个函数需要被默认为next
。 - 需要支持多个订阅。
具体实现如下:
class Observable { constructor(subscribe) { this._subscribe = subscribe; } subscribe(observerOrNext, error, complete) { let observer; if (typeof observerOrNext === 'function') { observer = { next: observerOrNext, error: error || (() => {}), complete: complete || (() => {}), }; } else { observer = observerOrNext; } const subscription = new Subscription(); const safeObserver = new SafeObserver(observer); subscription.add(safeObserver); const teardown = this._subscribe(safeObserver); if (typeof teardown === 'function') { subscription.add(new Subscription(teardown)); } return subscription; }}class SafeObserver { constructor(observer) { this._observer = observer; this._closed = false; } next(value) { if (!this._closed && this._observer.next) { try { this._observer.next(value); } catch (e) { this.error(e); } } } error(error) { if (!this._closed) { this._closed = true; if (this._observer.error) { try { this._observer.error(error); } catch (e) { console.error(e); } } this.unsubscribe(); } } complete() { if (!this._closed) { this._closed = true; if (this._observer.complete) { try { this._observer.complete(); } catch (e) { console.error(e); } } this.unsubscribe(); } } get closed() { return this._closed; } unsubscribe() { this._closed = true; if (this._observer.unsubscribe) { this._observer.unsubscribe(); } }}class Subscription { constructor(teardown) { this._closed = false; if (teardown) { this._teardown = teardown; } } add(teardown) { if (teardown && teardown !== this) { if (this._closed) { teardown.unsubscribe(); } else { if (!(teardown instanceof Subscription)) { teardown = new Subscription(teardown); } if (!this._childSubscriptions) { this._childSubscriptions = []; } this._childSubscriptions.push(teardown); } } } unsubscribe() { this._closed = true; if (this._teardown) { try { this._teardown(); } catch (e) { console.error(e); } } if (this._childSubscriptions) { while (this._childSubscriptions.length) { const childSubscription = this._childSubscriptions.shift(); childSubscription.unsubscribe(); } } }}
上述代码中,我们使用SafeObserver
类包装原始的Observer
,以处理错误和取消订阅等问题。Subscription
类表示一个订阅,它可以包含一个或多个子订阅,以便在取消订阅时一起取消。在subscribe
方法中,我们先判断传入的observerOrNext
参数类型,如果是函数,则将其视为next
回调函数,并创建一个新的Observer
对象,否则直接使用传入的observerOrNext
作为Observer
对象。接着创建一个新的Subscription
对象,并用它来存储订阅的相关信息。使用SafeObserver
类包装Observer
,并向Observable
的subscribe
方法传入它,从而将订阅的处理逻辑安全地封装在SafeObserver
类中。在订阅时,我们还可支持多个订阅,增加了复用和可扩展性。