我正在尝试创建2个observable,它基本上都是反向操作。它是一个服务发现端点,因此在启动应用程序时,必须尝试注册服务发现直到成功。所以我想创建一个像这样的可观察对象:
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()
操作,然后{{1} }操作不应该再运行了。
.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);
},
}
}
时,它会订阅.takeUntil()
,它会开始执行删除操作,这会立即停止delete$
观察。
我尝试过做create$
,但它同时订阅了两者,所以不起作用。我也试过做takeUntil(Observable.merge(Observable.never(), delete$))
第一个永远不会结束(:P),第二个永远不会订阅。
答案 0 :(得分:4)
大多数Observable都是冷和单播。这是一个冗长的主题,因此我将在大多数情况下遵循伟大的文章Hot vs Cold Observables,但总结一下:
COLD是您的observable创建生产者
的时候// COLD var cold = new Observable((observer) => { var producer = new Producer(); // have observer listen to producer here });
HOT是您的观察者关闭生产者
的时候// HOT var producer = new Producer(); var hot = new Observable((observer) => { // have observer listen to producer here });
在您的示例中,这是一个重要的区别,因为create$
和delete$
都很冷。正如您所发现的那样,为delete$
提供takeUntil
会导致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,我们就可以执行shutdown$.next()
副作用。
答案 1 :(得分:1)
方法#1
您可以在.takeUntill
中使用Observable而无需通过创建中间Subject
实际订阅它。然后您可以订阅该主题而不是原始主题。像这样的东西:
const delete$ = new Subject();
...
create() {
return create$
.takeUntill(delete$);
},
delete() {
create(...).subscribe(delete$);
return delete;
}
方法#2
但是在你的情况下,我认为创建主题会更好,这会在调用.delete
时通知。像这样:
const onDelete$ = new Subject();
...
create() {
return create$
.takeUntill(onDelete$);
},
delete() {
onDelete$.next();
return ...
}