Rxjs 正确使用takeUntil()停止observable
我试图创建两个观测值,它们基本上做逆运算。它是服务发现端点,因此在启动应用程序时,它必须尝试注册到服务发现,直到成功。所以我想创造一个这样的可观察的物体:Rxjs 正确使用takeUntil()停止observable,rxjs,observable,observer-pattern,rxjs5,Rxjs,Observable,Observer Pattern,Rxjs5,我试图创建两个观测值,它们基本上做逆运算。它是服务发现端点,因此在启动应用程序时,它必须尝试注册到服务发现,直到成功。所以我想创造一个这样的可观察的物体: const create$ = Rx.Observable.create((observer) => { observer.next('Trying to create observation'); sp.put(endpoint, { json: true }, (err, res, payload) => {
const create$ = Rx.Observable.create((observer) => {
observer.next('Trying to create observation');
sp.put(endpoint, { json: true }, (err, res, payload) => {
err ? observer.error(err) : observer.complete();
});
});
当应用程序正常关闭时,我想执行反向操作。像这样:
const delete$ = Rx.Observable.create((observer) => {
console.log('deleted subscribed');
observer.next('Trying to delete observation');
sp.delete(endpoint, { json: true }, (err, res, payload) => {
err ? observer.error(err) : observer.complete();
});
});
因此,我决定创建一个函数,该函数返回一个具有.create和.delete的对象。我想解决的问题是,当应用程序启动并尝试注册时,但无法到达服务发现端点,然后应用程序启动其正常关闭过程并调用.delete操作,那么.create操作将不再运行
function observe({ url, version, serviceName }) {
const endpoint = `/endpoint/${serviceName}/${version}/${encodeURIComponent(url)}`;
const create$ = Rx.Observable.create((observer) => {
observer.next('Trying to create observation');
sp.put(endpoint, { json: true }, (err, res, payload) => {
err ? observer.error(err) : observer.complete();
});
});
const delete$ = Rx.Observable.create((observer) => {
console.log('deleted subscribed');
observer.next('Trying to delete observation');
sp.delete(endpoint, { json: true }, (err, res, payload) => {
err ? observer.error(err) : observer.complete();
});
});
return {
create() {
return create$.retry(Number.POSITIVE_INFINITY).takeUntil(delete$); // This is where I would want to takeUntil()
},
delete({ interval = 5000, times = 0 } = {}) {
return delete$.retry(times);
},
}
}
我的问题是,当使用.take时,直到它订阅delete$,它开始执行delete操作,该操作的效果是立即停止create$observable
我尝试过使用takentilobservable.mergeObservable.never,delete$,但它同时订阅了这两个版本,因此不起作用。我还试着做了takentilobservable.concatObservable.never,删除$第一个永远不会结束:P第二个永远不会订阅 大多数可见光是冷的和单播的。这是一个有点冗长的话题,因此我将在很大程度上遵循这篇伟大的文章,但概括起来:
冷是当你的可观察创造了生产者
热是当你的可观察到的关闭生产者
在您的示例中,这是一个关键的区别,因为create$和delete$都是冷的。正如您所发现的,向takeUntil提供delete$会导致订阅delete$,从而启动请求
如果您想保持代码的结构/API不变,实现这一点的一种方法是使用被视为通知程序的主题。主题是多播和热门的,即使他们自己不做任何事情
function observe({ url, version, serviceName }) {
// etc...
const shutdown$ = new Subject(); // <---------------- create our notifier
return {
create() {
return create$
.retry(Number.POSITIVE_INFINITY)
.takeUntil(shutdown$); // <-------------------- take our notifier
},
delete({ interval = 5000, times = 0 } = {}) {
return Observable.defer(() => {
shutdown$.next(); // <------------------------- notify
return delete$.retry(times);
});
}
};
}
我们使用了Observable.defer,这样我们就可以在有人实际订阅我们返回的Observable时执行关闭$。下一个副作用。大多数观察都是冷的和单播的。这是一个有点冗长的话题,因此我将在很大程度上遵循这篇伟大的文章,但概括起来:
冷是当你的可观察创造了生产者
热是当你的可观察到的关闭生产者
在您的示例中,这是一个关键的区别,因为create$和delete$都是冷的。正如您所发现的,向takeUntil提供delete$会导致订阅delete$,从而启动请求
如果您想保持代码的结构/API不变,实现这一点的一种方法是使用被视为通知程序的主题。主题是多播和热门的,即使他们自己不做任何事情
function observe({ url, version, serviceName }) {
// etc...
const shutdown$ = new Subject(); // <---------------- create our notifier
return {
create() {
return create$
.retry(Number.POSITIVE_INFINITY)
.takeUntil(shutdown$); // <-------------------- take our notifier
},
delete({ interval = 5000, times = 0 } = {}) {
return Observable.defer(() => {
shutdown$.next(); // <------------------------- notify
return delete$.retry(times);
});
}
};
}
我们使用了Observable.defer,这样我们就可以在有人实际订阅我们返回的Observable时执行关闭$。下一个副作用。方法1
您可以在.takentill中使用Observable,而无需通过创建中间主题来实际订阅它。然后你可以订阅该主题而不是原始主题。大概是这样的:
方法2
然而,在您的情况下,我认为最好创建subject,它将在调用.delete时发出通知。这样地:
方法1
您可以在.takentill中使用Observable,而无需通过创建中间主题来实际订阅它。然后你可以订阅该主题而不是原始主题。大概是这样的:
方法2
然而,在您的情况下,我认为最好创建subject,它将在调用.delete时发出通知。这样地:
您的重试逻辑正确吗?描述使它听起来像是创建是一个重试?@jayphelps我更新了创建上的重试逻辑。我想在创建时无限期地重复,但如果删除开始尝试,则停止。您的重试逻辑正确吗?描述使它听起来像是创建是一个重试?@jayphelps我更新了创建上的重试逻辑。我想无限期地重复创建,但如果删除开始尝试,请停止
function observe({ url, version, serviceName }) {
// etc...
const shutdown$ = new Subject(); // <---------------- create our notifier
return {
create() {
return create$
.retry(Number.POSITIVE_INFINITY)
.takeUntil(shutdown$); // <-------------------- take our notifier
},
delete({ interval = 5000, times = 0 } = {}) {
return Observable.defer(() => {
shutdown$.next(); // <------------------------- notify
return delete$.retry(times);
});
}
};
}
const delete$ = new Subject();
...
create() {
return create$
.takeUntill(delete$);
},
delete() {
create(...).subscribe(delete$);
return delete;
}
const onDelete$ = new Subject();
...
create() {
return create$
.takeUntill(onDelete$);
},
delete() {
onDelete$.next();
return ...
}