Angular 7 Rxjs - In-Flight HTTP-запрос не отменяется для подписки - PullRequest
1 голос
/ 30 марта 2019

У меня проблемы с пониманием, почему отмена подписки на подписку rxjs с добавленным шагом не отменяет запрос http в полете.

Взгляните на: https://stackblitz.com/edit/angular5-http-example-nx8fza

Вы заметите на вкладке сети для Chrome, один щелчок отменяет запросы, а другой нет.

 getJoke(): void {
    this.jokeSub = this.api.getData()
      .subscribe(data => this.joke = data);

    this.jokeSub.unsubscribe();
  }

  // This method does not cancel requests in flight because of the .add step.
  getJoke2(): void {
    this.jokeSub2 = this.api.getData()
      .subscribe(data => this.joke = data).add(console.log("Added step"));

    this.jokeSub2.unsubscribe();
  }

cancel request

Примечание: я сталкивался с этим, когда настраивал перехватчик http в Angular 7 с помощью rxjs 6. Я не мог отменить запросы, когда у моего перехватчика была какая-то логика в канале. Я думаю, что если я смогу понять, почему это не работает, я могу ответить на мой более конкретный вопрос.

Ответы [ 2 ]

1 голос
/ 31 марта 2019

Как уже объясняется в другом ответе, как работает rxjs, я также добавляю, как вы должны изменить свой код, чтобы он работал, как в первом примере.

getJoke2(): void {
    this.jokeSub2 = this.api.getData()
      .subscribe(data => this.joke = data);
    this.jokeSub2.add(console.log("Added step"));

    this.jokeSub2.unsubscribe();
}

Также ссылка на развилку вашего StackBlitz, где вы можете увидеть, как он работает.

1 голос
/ 31 марта 2019

Метод .add добавляет логику разрыва и возвращает новую подписку для этой логики разрыва. Эта новая подписка добавляется как внутренняя подписка к первоначальной. Таким образом, эти подписки имеют отношения между родителями и ребенком, и если вы отмените подписку от родителя - ребенок также удаляется.

Хотя отписка от детей не завершит родитель.

Вот объяснение из документации по методу добавления

Возвращает подписку, использованную или созданную для добавления во внутренний список подписок. Эту подписку можно использовать с методом remove (), чтобы удалить переданную логику удаления из внутреннего списка подписок.

Вот игровая площадка для этого. Попробуйте закомментировать некоторые тайм-ауты:

const { timer } = rxjs;
const { finalize, take } = rxjs.operators;

const startedAt = Date.now();

const a = timer(0, 300).pipe(
    finalize(createTeardown('a')),
    take(10)
  )
  .subscribe(console.log);

const b = a.add(createTeardown('b'));
const c = a.add(createTeardown('c'));

// Try commenting out some of these
setTimeout(()=>a.unsubscribe(), 1000);
setTimeout(()=>b.unsubscribe(), 1000);
setTimeout(()=>c.unsubscribe(), 1000);


function createTeardown(name) {
  return () => console.log(name, Date.now() - startedAt);
}
<script src="https://unpkg.com/rxjs@6.4.0/bundles/rxjs.umd.min.js"></script>

Чтобы исправить конкретный пример кода, вам нужно отдельно хранить исходную подписку:

getJoke2(): void {
  this.jokeSub2 = this.api.getData()
    .subscribe(data => this.joke = data); // parent subscription (a)

  this.jokeSub2
    .add(() => console.log('Child teardown logic')); // child subscription (b)

  this.jokeSub2.unsubscribe();
}

ПРИМЕЧАНИЕ: это в основном дублирует ответ AlesD. Объединяя это в один ответ для прозрачности

Надеюсь, это поможет

...