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 ...
}