операнд first () не публикуется после второго вызова внутри функции - PullRequest
1 голос
/ 10 марта 2019

Я не понимаю, почему это не работает, но альтернативы ниже.

app.component.ts

import { Component } from '@angular/core';
import { Subject, Observable } from 'rxjs';
import { first } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  id = 0;
  obs = new Subject();

  changeValue() {
    this.fakeApiCall(this.id++)
      .pipe(first())
      .subscribe(this.obs);
  }

  fakeApiCall(id: number) {
    return new Observable(observer => {
      console.log('called with id ' + id);
      observer.next({ items: [id, Math.random()] });
    });
  }
}

app.component.html

<h1>
    <div *ngIf="(obs | async) as v">
        <ul>
            <li *ngFor="let item of v.items">
                {{ item }}
            </li>
        </ul>

        <ul>
            <li *ngFor="let item of v.items">
                {{ item }}
            </li>
        </ul>
    </div>

    <div *ngIf="(obs | async) as v">
        <ul>
            <li *ngFor="let item of v.items">
                {{ item }}
            </li>
        </ul>

        <ul>
            <li *ngFor="let item of v.items">
                {{ item }}
            </li>
        </ul>
    </div>

    <button (click)="changeValue()">increase counter</button>
</h1>

Когда я нажимаю кнопку «увеличить счетчик», он сначала получает значения, но не потом, в то время как эти альтернативы работают просто отлично:

changeValue() {
    this.fakeApiCall(this.id++)
      .subscribe(this.obs)
      .unsubscribe();
  }

или

changeValue() {
    this.fakeApiCall(this.id++)
      .pipe(take(2)) // NOTES: if I write take(1), it has the same effect.
      .subscribe(this.obs);
  }

Я запутался, это ошибка или что здесь на самом деле происходит?

РЕДАКТИРОВАТЬ: если вы хотите, чтобы URL-адрес stackblitz, здесь: https://stackblitz.com/edit/angular-28eyiy

1 Ответ

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

Это не ошибка, проблема в том, что вы подписываетесь Subject на subscribe(this.obs).

Когда вы используете subscribe(this.obs), вы передаете все уведомления вашему экземпляру Subject. Это означает next, complete и error уведомления. И вот в чем проблема: first() завершит цепочку после первой эмиссии (кстати, см. Angular 2 с использованием RxJS - возьмите (1) vs first () ), что означает, что она пройдет один next и одно complete уведомление. Когда Subject получает уведомление complete, оно останавливается и никогда не будет переиздавать что-либо, даже если вы снова подпишете его на другую цепочку (это является частью "Наблюдаемого контракта" ).

Таким образом, если вы хотите использовать один и тот же Subject в нескольких подписках, когда вы знаете, что они будут завершены, вы можете передать только уведомление next и ничего более (Subject останется активным):

.subscribe(v => this.obs.next(v));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...