【问题标题】:How can i get values from observable without using subscribe如何在不使用订阅的情况下从 observable 获取值
【发布时间】:2020-11-25 14:22:07
【问题描述】:

当我开始学习 Angular 时,我读过一些博客说使用异步管道更好,因为它会自动取消订阅数据流。所以我愿意

HTML

<div *ngIf="users | async">
    <ul>
        <li *ngFor="let user of users | async">{{ user.name }}</li>
    </ul>
</div>

TS 文件

export class AppComponent implements OnInit {
  constructor(private http: HttpClient) {};
  users: any;
  ngOnInit() {
   this.users = this.http.get('https://jsonplaceholder.typicode.com/userss');
   console.log(this.users);
  }
}

所以在 ngOnInit 方法中控制台日志

console.log(this.users);

给我

Observable {_isScalar: false, source: Observable, operator: MapOperator

我通过异步管道获得了 HTML 中的值,但是如果我需要根据从后端获得的用户在我的组件 - ts 文件中执行一些逻辑。

如果我想要里面的数据,我可以通过订阅来完成。但我不希望这样,因为首先我从异步管道开始,因为我不想手动取消订阅它。

所以在这种情况下,我如何在不订阅的情况下从 observable 中获取值,所以最后当 组件被破坏了我不应该关心退订。

【问题讨论】:

  • 我不想转换成promise
  • 如果您不想将 this.user 转换为 Promise,您可以创建另一个变量并将用户数据存储在其中。
  • 如果转换为承诺,如果唯一能做到这一点,那么好吧......
  • 您实际上想对组件中的users 做什么?如果您从模板调用组件中的函数,则可以将模板中的users 传递给该函数,并以这种方式访问​​函数中的用户。

标签: angular rxjs


【解决方案1】:

如果你想在 Observable 中做一些转换,只需使用map pipe-able 操作符:

onlyActiveUsers: Observable<any>;

ngOnInit() {
   this.onlyActiveUsers$ = this.http
     .get('https://jsonplaceholder.typicode.com/userss')
     .pipe(
        map(users => {
           const transformedUsers = users.filter(user => user.isActive);
           return transformedUsers;
        })
     )
  }

您可以在模板中使用| async 管道作为变量onlyActiveUsers$

如果您想在转换之前或之后在组件中存储一些值,请使用tap

onlyActiveUsers: Observable<any[]>;
allUsers: any[];

ngOnInit() {
   this.onlyActiveUsers$ = this.http
     .get('https://jsonplaceholder.typicode.com/userss')
     .pipe(
        tap(allUsers => this.allUsers = allUsers), // here, or after "map" below
        map(users => {
           const transformedUsers = users.filter(user => user.isActive);
           return transformedUsers;
        })
     )
  }

【讨论】:

    【解决方案2】:

    我知道这并不能回答您最初关于如何获得 没有订阅的价值,但我正在发布你可能不知道的内容 这种从订阅模拟异步行为的方法 管道。


    根据下面 maxime 的评论,您也可以实现 takeUntil 运算符作为解决方案。

    • 请参考下面他对差异的解释。

      ngUnsubscribe: Subject<void> = new Subject<void>();
      
      this.http.get('https://jsonplaceholder.typicode.com/userss')
           .pipe(takeUntil(this.ngUnsubscribe))
           .subscribe(val => this.users = val)
      
      ngOnDestroy() {
         this.ngUnsubscribe.next();
      }
      

    我为此使用take 运算符。

    https://rxjs-dev.firebaseapp.com/api/operators/take

    take 返回一个仅发出第一个计数值的 Observable 由源 Observable 发出。如果源发出少于计数 values 然后发出它的所有值。 After that, it completes, regardless if the source completes.

    波纹管将采用一个值并自动取消订阅,类似于异步管道。

    this.http.get('https://jsonplaceholder.typicode.com/userss')
      .pipe(take(1))
      .subscribe(val => this.users = val)
    

    【讨论】:

    • 这与异步管道完全不同。异步管道保持流打开,直到其主机被销毁。无论是因为此级别存在 ngIf 还是主机组件正在被破坏(例如,ngIf 更高或新路由)。因此,如果您正在进行一个 HTTP 调用,该调用需要 10 秒才能解决并且您移动到另一个组件,即使组件被销毁,带有 take(1) 的选项仍将在后台运行,但这不会是异步管道的情况。如果你想要一个等价物,你可以挂钩到 ngOnDestroy,在主题中发出 void 并执行 takeUntil
    • @maxime1992 这是真的,我已经将您的方法作为一个可行的实现包含在内,并且使用take 方法围绕HTTP.get 肯定是一个值得关注的问题
    【解决方案3】:

    您使用异步管道的方法非常好。但是它会为你做的是订阅 observable,因为你得到了数据。它也会处理取消订阅,因为使用异步管道非常方便。

    这就是 observables 的本质:只有订阅它才能获得值。

    如果您想在组件中包含需要订阅的值。

    【讨论】:

      猜你喜欢
      • 2020-04-19
      • 1970-01-01
      • 2020-10-17
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多