【问题标题】:Access the return object from an observable 'synchronously'从可观察的“同步”访问返回对象
【发布时间】:2018-11-21 23:47:23
【问题描述】:

有没有办法直接访问 observable 的“有效负载”,并在以后解决它,而不必订阅?

例如,我知道我们可以做到这一点..

export class RecordService
{
   fetchRecordFromServer():Observable<Record>
   {
       return http.get().pipe(map(result => return new Record())); // equivalent
   }  
}


export class MyComponent
{
  public record:Record = null;
  constructor(private recordService:RecordService) 
  {
     this.userService.fetchRecordFromServer().subscribe( record => 
     {
        this.record = record;
     }); 
  }
  getRecordName():string
  {
     return this.record? this.record.name || "";
  }
}

我只是想知道是否有一种速记方法可以做这样的事情

export class MyComponent
{
  public record:Observable<Record>;
  constructor(private recordService:RecordService) 
  {
     this.record = this.userService.fetchRecordFromServer();
  }

  getRecordName():string
  {
     return this.record? this.record.name || "";
  }

}

我不完全确定我在问什么,但我认为我所追求的是可以从类型的 Observable 分配一个值,并且会在 Observable 触发时解决,并且可以被视为如果它是一直以来的一个实例。

也许 Promise 可以做到这一点,或者这是一个非常愚蠢的问题。我只是觉得我想说'将此变量设置为将很快实例化的实例,但是您可以尝试立即安全地使用它,并且因为可观察对象是类型,所以它会将其视为输入...

【问题讨论】:

  • 你能解释一下为什么你不能使用 subscribe 或者你的 this.record 的确切用例是什么?您是否试图避免多次 HttpClient 调用?您是否尝试在模板中渲染 this.record 并在未定义时遇到错误?
  • 您可以使用 await 关键字,但您必须将 observable 转换为 Promise
  • Ben Lesh medium.com/@benlesh/…的文档
  • @AlexanderStaroselsky - 我没有在模板中使用它。我的问题背后的想法是避免数百个订阅。例如,我有一个需要重复获取用户名的大型企业应用程序。我可以使用“热”的 observable,并让所有东西都订阅它,但感觉真的很笨拙。只要我只想在 UI 中使用用户名,异步管道就可以正常工作。我只是想知道 Observables/Promises 是否还有其他选项我错过了......但看起来可能没有。

标签: angular rxjs observable


【解决方案1】:

我认为通过您添加的代码,您正在尝试将 UI 直接绑定到热可观察对象。您可以使用 Async 管道来执行此操作: https://angular.io/api/common/AsyncPipe

来自documentation

import { Component } from '@angular/core';
import { Observable, interval } from 'rxjs';
import { map, take } from 'rxjs/operators';

@Component({
  selector: 'app-hero-message',
  template: `
      <h2>Async Hero Message and AsyncPipe</h2>
	    <p>Message: {{ message$ | async }}</p>
	    <button (click)="resend()">Resend</button>`,
})
export class HeroAsyncMessageComponent {
  message$: Observable < string > ;

  private messages = [
    'You are my hero!',
    'You are the best hero!',
    'Will you be my hero?'
  ];

  constructor() {
    this.resend();
  }

  resend() {
    this.message$ = interval(500).pipe(
      map(i => this.messages[i]),
      take(this.messages.length)
    );
  }
}

【讨论】:

  • 感谢您。我实际上并没有在 UI 中使用它。我认为这就是我做得不好的地方。我正在寻找异步管道的等价物,但在代码本身中。所以我可以说'这将是一个 User() 但它暂时不会出现,但当它出现时,使用名字和姓氏。我知道 subscribe 会做到这一点,但我想知道是否有一种“更聪明”的方式来做到这一点,就像 UI 中的异步一样
  • 嗯,好的。 subscribe 实际上是异步管道中发生的事情。当你有异步的东西时,你需要设置一个回调来处理它
【解决方案2】:

您可以在模板中使用async 管道,这样组件内部就没有订阅用法。

export class MyComponent
{
    public record$: Observable<Record>;
    constructor(private recordService:RecordService) 
    {
        this.record$ = this.userService.fetchRecordFromServer();
    }

    getRecordName(record: Record):string
    {
        return record ? record.name : "";
    }
}

在模板中

   <h1>{{getRecordName(records$ | async)}}</h1>

【讨论】:

    猜你喜欢
    • 2018-04-11
    • 2020-03-21
    • 2017-07-12
    • 2018-12-16
    • 2023-04-01
    • 2019-02-18
    • 2013-12-20
    • 1970-01-01
    • 2022-11-09
    相关资源
    最近更新 更多