【问题标题】:first() operand does not publish after a second call inside a functionfirst() 操作数在函数内的第二次调用后不发布
【发布时间】:2019-03-10 10:03:37
【问题描述】:

我不明白为什么这不起作用,但下面的替代方法可以。

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);
  }

我很困惑这是一个错误还是这里到底发生了什么?

编辑:如果你想要 stackblitz 网址,这里:https://stackblitz.com/edit/angular-28eyiy

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    这不是错误,问题在于您使用 subscribe(this.obs) 订阅 Subject 的方式。

    当您使用subscribe(this.obs) 时,您会将所有通知传递给您的Subject 实例。这意味着nextcompleteerror 通知。这就是问题所在,first() 将在第一次发射后完成链(顺便说一句,请参见 Angular 2 using RxJS - take(1) vs first()),这意味着它将通过一个 next 和一个 complete 通知。当Subject 收到complete 通知时,它会停止并且永远不会重新发送任何内容,即使您再次订阅不同的链(这是"The Observable Contract" 的一部分)。

    因此,如果您想在多个订阅中使用相同的Subject,并且您知道它们会完成,您可以只传递next 通知,仅此而已(Subject 将保持活动状态):

    .subscribe(v => this.obs.next(v));
    

    【讨论】:

    • 啊!好消息,从没想过完整的通知。干得好,伙计,谢谢!
    猜你喜欢
    • 2018-11-12
    • 1970-01-01
    • 2022-12-09
    • 2023-04-09
    • 2013-04-08
    • 1970-01-01
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多