【问题标题】:How do I emit the value of an observable to an rxjs Subject?如何将 observable 的值发送给 rxjs 主题?
【发布时间】:2019-02-24 04:45:34
【问题描述】:

我想从 Angular 服务中提供一个 rxjs Subject,以便能够通过调用服务上的方法来发出值(通过 next)。我希望它发出的值之一是 Angular HttpClient get 调用的结果。我似乎无法做到正确。我想知道为什么以下结果导致未调用订阅处理程序:

-查看

export default abstract class TileView implements OnInit {
  constructor (private configService : ConfigService) {}
  ngOnInit () {
    this.configService.fetch(this.type()).subscribe( res => {
      console.log(res)
    }); 
  }
}

-服务

export class ConfigService {
  public subject = new AsyncSubject();

  constructor (private http : HttpClient) {}

  fetch (type) {
    this.http.get(
      api.host + api.base + interpolate(api.config, { type }) + "/"
    ).subscribe( res => {
      this.subject.next(res);
    });

    return this.subject;
  }
}

有什么方法可以返回主题并通过单个方法调用触发 http 调用?这很奇怪,因为返回了主题,注册了订阅者,http 调用完成并调用了this.subject.next(res),但订阅处理程序甚至没有运行。

【问题讨论】:

  • 你在哪里订阅这个主题?您已经创建了“下一个”,但在听什么?
  • 主题是从我在那里显示的视图中调用fetch 返回的。 subscribe 正在那里发生。
  • 我不确定我是否完全理解您想要达到的目标。如果您订阅 fetch,它将返回您获取的结果。只需在需要结果的任何地方调用 service.fetch 即可。 Http.get 构造一个 observable。 angular.io/api/common/http/HttpClient
  • 这就是我的意思是它不起作用。我正在订阅 fetch 并且订阅者永远不会触发,即使 http 调用已成功完成数据。
  • http.get 已经是可观察的,可以在没有主题的情况下订阅。只需从您的 get 订阅中返回 res 即可,我认为您不需要这样的订阅:fetch (type) { this.http.get( api.host + api.base + interpolate(api.config, { type }) + "/" ).subscribe( res => { return res });

标签: angular rxjs observable behaviorsubject


【解决方案1】:

订阅您认为不获取的“主题”。也无需从您的服务中返回主题。

查看:

export default abstract class TileView implements OnInit {
  constructor (private configService : ConfigService) {}
  ngOnInit () {
    this.configService.subjectChanged(this.type()).subscribe( res => {
      console.log(res)
    }); 
  }
}

服务: 导出类 ConfigService {

  public subjectChanged = new Subject();

  constructor (private http : HttpClient) {}

  fetch (type) {
    this.http.get(
      api.host + api.base + interpolate(api.config, { type }) + "/"
    ).subscribe( res => {
      this.subjectChanged.next(res);
    });
  }
}

【讨论】:

  • 我之所以从 fetch 返回它,是因为我想触发 http 调用并通过调用单个方法来获取主题的句柄。
  • @Shahana 使用 Pierre 的方法,当任何客户端代码使用 fetch() 时,所有观察者都将获得传播的值,而不仅仅是调用者(因为他们都订阅了 same可观察)。
【解决方案2】:

Pierre,发生这种情况的原因是,AsyncSubject 仅在 observable完成(由 Subject.prototype.complete() 确定)时发出最后一个值。

在您的情况下,您可能希望为订阅者使用 BehaviorSubject,它会发出流中的最后一个值,而不管是否完成:

AsyncSubject 发出最后一个值(并且只有最后一个值) 由源 Observable,并且仅在源 Observable 之后 完成。 (如果源 Observable 没有发出任何值,则 AsyncSubject 也可以在不发出任何值的情况下完成。)

Subject Documentation

更新:

如果您因为初始值传播而不愿意使用 BehaviorSubject,请使用 ReplaySubject(1)。

【讨论】:

  • 老兄......但我不想使用 BehaviorSubject 的原因是因为它需要一个初始值,在我的情况下,我希望初始值是 http 调用的结果。
  • 你可以使用 ReplaySubject(1) :)
  • 只需将我的AsyncSubject 换成ReplaySubject 就会导致代码开始像我希望的那样工作...... :)
  • 太棒了,伙计,很高兴听到这个消息:)
【解决方案3】:

完成 observable,它就会工作

fetch (type) {
    this.http.get(
      api.host + api.base + interpolate(api.config, { type }) + "/"
    ).subscribe( res => {
      this.subject.next(res);
      this.subject.complete();
    });

    return this.subject;
  }

另一种方法是使用 BehaviourSubject,在这种情况下,您需要处理 null 检查,因为 BehaviourSubject 需要默认值

public behaviourSub = new BehaviorSubject(null);

this.configService.fetch(this.type()).subscribe( res => {
    if (res !== null) {
      // actual value emitted
    }
});

【讨论】:

  • 你说得对。我发现我错过了上面@Rafael 答案的完整内容。我从 BehaviorSubject 开始,但后来意识到我在构造它时需要一个初始值,我不想这样做。
【解决方案4】:

AsyncObservable 的一个特殊性是他在发送信息之前等待“complete()”完成

由于 AsyncSubject 扩展了 Observable,因此没有必要,但我建议您使用“return this.subject.asObservable()”,它是“Subject”对象的一部分。由于您需要在其他类型的主题上使用它,例如,如果您通过 BehaviourSubject 更改主题的类型,则无需更改代码;)

【讨论】:

    猜你喜欢
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    相关资源
    最近更新 更多