可以将HTTPClient与Angular中的RXJ组合组合

发布于 2025-02-12 17:53:49 字数 3392 浏览 1 评论 0原文

I want to create a service that will hold the data received from REST API than emits it to whom ever needs it.
I used BehaviorSubject and managed to get the data in the template (using *ngFor) but whatever I tried, I can't get it in a component. The flow is that a some component calls fetchCustomersDetails than renders the data as a list.
Once the user clicks a customer, the name passed to another page where I wish to filter the data in the service and retrieve the match.
Examine the code shows that the name of the customer (from the list fetched in the service) is passed to getCustomerByCompanyName but the subject contain an empty array where the data needs to be saved.
I'm very new to Angular and it seems I'm missing some concept of using observables.
Thank you for your help.
Here is what I tried so far:

    /* Service */
    export class CustomerDetailsService {
      private apiUrl: string = `https://...`;
      private readonly customersDetailsPool$: BehaviorSubject<ICustomerDetails[]> = new BehaviorSubject<ICustomerDetails[]>([]);
    
      constructor(private http: HttpClient) { }
    
      fetchCustomersDetails(){
        return this.http.get<ICustomerDetails[]>(this.apiUrl)
          .subscribe({
            next: ((customerDetailsList: ICustomerDetails[]) => this.customersDetailsPool$.next(customerDetailsList)),
            error: ((error: any) => this.handleError(error)),
            complete: (() => console.log("test: ", this.customersDetailsPool$))
          })
      }
    
      get customersDetailsPool(): Observable<ICustomerDetails[]> {
        return this.customersDetailsPool$.asObservable();
      }
    
      getCustomerByCompanyName(name: string) {
        console.log("customersDetailsPool: ", this.customersDetailsPool$);
        return this.customersDetailsPool$.pipe(
          map((customers: ICustomerDetails[]) => {customers.find((customer) => {customer.company === name})})
        )
      }
    }
    /* component */
    @Component({
      selector: 'app-customer-edit-page',
      templateUrl: './customer-edit-page.component.html',
      styleUrls: ['./customer-edit-page.component.scss'],
      providers: [CustomerDetailsService]
    })
    
    export class CustomerEditPageComponent implements OnInit, AfterViewInit {
      @ViewChild(CustomerDetailsComponent)
      private customerNewDetails!: CustomerDetailsComponent;
      customerName: string | null = '';
      isEdit: boolean = false;
      customerDetails: ICustomerDetails = {
        company: '',
        contacts: [],
      };
      
      constructor(
        private router: Router,
        private route: ActivatedRoute,
        public customerDetailsService: CustomerDetailsService,
      ) { }
    
      ngOnInit(): void {
        this.customerName = this.route.snapshot.paramMap.get('company');
        this.isEdit = this.isToEdit();
        if (this.customerName) {
          this.customerDetailsService.getCustomerByCompanyName(this.customerName)
          .subscribe((customer) => {
            if (customer) {
              this.customerDetails = customer;
            }
          })
          .unsubscribe();
        }
      }
    }

I want to create a service that will hold the data received from REST API than emits it to whom ever needs it.
I used BehaviorSubject and managed to get the data in the template (using *ngFor) but whatever I tried, I can't get it in a component. The flow is that a some component calls fetchCustomersDetails than renders the data as a list.
Once the user clicks a customer, the name passed to another page where I wish to filter the data in the service and retrieve the match.
Examine the code shows that the name of the customer (from the list fetched in the service) is passed to getCustomerByCompanyName but the subject contain an empty array where the data needs to be saved.
I'm very new to Angular and it seems I'm missing some concept of using observables.
Thank you for your help.
Here is what I tried so far:

    /* Service */
    export class CustomerDetailsService {
      private apiUrl: string = `https://...`;
      private readonly customersDetailsPool$: BehaviorSubject<ICustomerDetails[]> = new BehaviorSubject<ICustomerDetails[]>([]);
    
      constructor(private http: HttpClient) { }
    
      fetchCustomersDetails(){
        return this.http.get<ICustomerDetails[]>(this.apiUrl)
          .subscribe({
            next: ((customerDetailsList: ICustomerDetails[]) => this.customersDetailsPool$.next(customerDetailsList)),
            error: ((error: any) => this.handleError(error)),
            complete: (() => console.log("test: ", this.customersDetailsPool$))
          })
      }
    
      get customersDetailsPool(): Observable<ICustomerDetails[]> {
        return this.customersDetailsPool$.asObservable();
      }
    
      getCustomerByCompanyName(name: string) {
        console.log("customersDetailsPool: ", this.customersDetailsPool$);
        return this.customersDetailsPool$.pipe(
          map((customers: ICustomerDetails[]) => {customers.find((customer) => {customer.company === name})})
        )
      }
    }
    /* component */
    @Component({
      selector: 'app-customer-edit-page',
      templateUrl: './customer-edit-page.component.html',
      styleUrls: ['./customer-edit-page.component.scss'],
      providers: [CustomerDetailsService]
    })
    
    export class CustomerEditPageComponent implements OnInit, AfterViewInit {
      @ViewChild(CustomerDetailsComponent)
      private customerNewDetails!: CustomerDetailsComponent;
      customerName: string | null = '';
      isEdit: boolean = false;
      customerDetails: ICustomerDetails = {
        company: '',
        contacts: [],
      };
      
      constructor(
        private router: Router,
        private route: ActivatedRoute,
        public customerDetailsService: CustomerDetailsService,
      ) { }
    
      ngOnInit(): void {
        this.customerName = this.route.snapshot.paramMap.get('company');
        this.isEdit = this.isToEdit();
        if (this.customerName) {
          this.customerDetailsService.getCustomerByCompanyName(this.customerName)
          .subscribe((customer) => {
            if (customer) {
              this.customerDetails = customer;
            }
          })
          .unsubscribe();
        }
      }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

如梦亦如幻 2025-02-19 17:53:49

查找调用中的语法错误。

customers.find((customer) => {customer.company === name})

这不会返回任何内容,要么添加返回或删除卷曲括号。

customers.find((customer) => {return customer.company === name})

customers.find((customer) => customer.company === name)

没有牙套,返回是隐式的。

设置它的方式,您还需要在某个时候调用fetchCustomerDetails(),并且您不能立即退缩,因为您不知道是否是的初始HTTP请求fetchcustomerDetails()已经完成,除非您有未显示的机制。


我只是注意到您在周围的地图调用中遇到了相同的错误。卸下牙套或也添加在那里。

      map((customers: ICustomerDetails[]) =>
        customers.find((customer) => customer.company === name)
      )

如果您仍然有任何差异,这是一个工作模拟。

https://stackblitz.com/edit/angular-ivy-17tsrm?file=src/app/customer-details.service.ts

You've got a syntax error in your find call.

customers.find((customer) => {customer.company === name})

This does not return anything, Either add return or remove the curly braces.

customers.find((customer) => {return customer.company === name})

OR

customers.find((customer) => customer.company === name)

Without braces, return is implicit.

The way you have it set up, you also need to call fetchCustomerDetails() at some point, and you can't just unsubscribe immediately, because you have no idea if the initial http request from fetchCustomerDetails() has completed yet, unless you have a mechanism in place that you haven't showed.


I just noticed you have the same error in the surrounding map call. Remove the braces or add return there as well.

      map((customers: ICustomerDetails[]) =>
        customers.find((customer) => customer.company === name)
      )

Here's a working simulation if you still have any discrepancies.

https://stackblitz.com/edit/angular-ivy-17tsrm?file=src/app/customer-details.service.ts

淡看悲欢离合 2025-02-19 17:53:49

您会立即从服务中取消订阅,这可能正在创建一些异步时正式问题

删除unsubscribe(),而是使用takeuntil - 您可以查找<<代码>带有ngondestroy的takeuntil

You're immediately unsubscribing from the service observable, which is probably creating some async timing issue

Remove the unsubscribe(), and instead use a takeUntil - you can lookup examples of takeUntil with ngOnDestroy

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文