简体   繁体   English

如何处理 Angular 中的 RxJS Observables 的异步性质

[英]How to handle asynchronous nature of RxJS Observables inside Angular

I'm new to Angular and the Observables architecture, and I'm having trouble running functions that have asynchronous code.我是 Angular 和 Observables 架构的新手,我在运行具有异步代码的函数时遇到了麻烦。

In the code below, I am using the AngularFire library to obtain information from a basic Firebase Realtime Database.在下面的代码中,我使用 AngularFire 库从基本的 Firebase 实时数据库中获取信息。 However, when I call the function searchForCompany() from one of my components, the observable doesn't load the required data instantly, meaning the HTML elements of my component don't get loaded properly.但是,当我从我的一个组件调用 function searchForCompany searchForCompany()时,可观察对象不会立即加载所需的数据,这意味着我的组件的 HTML 元素没有正确加载。 Am I using the Observables architecture wrong?我使用 Observables 架构错了吗?

import { SubscriptionData } from './interface'
import { Injectable } from '@angular/core';
import { AngularFireDatabase, AngularFireList } from '@angular/fire/database'

@Injectable({
  providedIn: 'root'
})

export class SubscriptionService {
  private dbRead: SubscriptionData[];
  private subscriptionData = new SubscriptionData;
  private databasePath = "/companies";
  private databaseRef: AngularFireList<SubscriptionData>;

  constructor(private _database: AngularFireDatabase) {
    this.databaseRef = _database.list(this.databasePath);
  }

  searchForCompany(service:String) {
    for (let key of this.dbRead) {
      //Search for name of a company in the Firebase database
      if (key.name == service) {
        this.subscriptionData=key;
        return;
      }
    }

  readDatabase() {
    this.databaseRef.valueChanges().subscribe(data=> {
      this.dbRead = data;
    })
  }
}

think about observable like about a stream that provides data.考虑像提供数据的 stream 一样可观察。 Your component should subscribe to this stream.你的组件应该订阅这个 stream。 Then a component will receive every new value from the stream.然后组件将从 stream 接收每个新值。

Some example here : 这里有一些例子:

@Component({
  selector: 'app-users-listing',
  templateUrl: './users-listing.component.html',
  styleUrls: ['./users-listing.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class UsersListingComponent {

  // THIS IS A "STREAM" AND YOU NEED TO SUBSCRIBE TO IT IN THE TEMPLATE OR INSIDE CODE
  users$: Observable<UserInterface[]> = this.activatedRoute.data.pipe(
    map(data => data.users),
  );

  constructor(
    private activatedRoute: ActivatedRoute,
  ) { }

}

Let's subscribe to users$ inside the template让我们在模板中订阅users$

<mat-list>
  <!-- "users$ | async" creates a subscription  -->
  <mat-list-item *ngFor="let user of (users$ | async)">
    <h3 matLine> {{ user.first_name + ' ' + user.last_name }} </h3>
    <p matLine>
      <span> {{user.email}} </span>
    </p>
  </mat-list-item>
</mat-list>

Regarding to your example.关于你的例子。 Try to change your service to return an Observable from the method and subscribe to it in your component.尝试更改您的服务以从该方法返回一个 Observable 并在您的组件中订阅它。 It could be like它可能就像

searchForCompany () {
  return this.databaseRef.valueChanges()
}

And subscribe to it in the component, transform received data, etc. It may looks like:并在组件中订阅它,转换接收到的数据等。它可能看起来像:

export class MyComponent {
  constructor (private service: SubscriptionService) {}

  ngOnInit(): void {
    this.service.searchForCompany().pipe(
      // SOME ADDITIONAL LOGIC
      // --> WRITE SOME CODE TO DESTROY SUBSCRIPTION HERE <---
    ).subscribe();
  }
}

OR create class property - observable.或创建 class 属性 - 可观察的。 And subscribe to it in template using async pipe并使用async pipe 在模板中订阅它

export class MyComponent {

  propert$ = this.service.searchForCompany().pipe(
    // SOME ADDITIONAL LOGIC
  )
  constructor (private service: SubscriptionService) {}
}

Hope it helps.希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM