以下为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
类中。在订阅时,我们还可支持多个订阅,增加了复用和可扩展性。