简体   繁体   English

BehaviorSubject 订阅未侦听值更改

[英]BehaviorSubject subscription not listening for value changes

I am creating an angular app where I have an API service.我正在创建一个 angular 应用程序,其中我有一个 API 服务。 This service calls API using axios and updates the value of BehaviorSubject as requires here is the code for that.此服务使用 axios 调用 API 并根据需要更新 BehaviorSubject 的值,这里是代码。

import { Injectable } from "@angular/core";
import axios, { AxiosInstance } from 'axios';
import { BehaviorSubject, Observable, Subject } from "rxjs";
import { Post } from "../mock/post.model";
@Injectable({
    providedIn: 'root',
})
export class APIService {

    private AxiosInstance = axios.create();

    private newsList: BehaviorSubject<Post[]>;
    private startupList: BehaviorSubject<Post[]>;
    private allPosts: Post[];
    constructor() {
        this.initBS();
    }

    initBS() {
        this.newsList = new BehaviorSubject<Post[]>(null);
        this.startupList = new BehaviorSubject<Post[]>(null);
    }

    getAllPosts(): void {
        this.AxiosInstance.get(MY_API_ENDPOINT)
            .then(data => {
                const resp: Post[] = this.mapNews(data.data);
                this.allPosts = resp;
                let tempNews: Post[] = [];
                let tempStartup: Post[] = [];
                for (const post of this.allPosts) {
                    for (const cat of post.category) {
                        if (cat.toLocaleLowerCase().includes('news')) {
                            tempNews.push(post);
                        }
                        if (cat.toLocaleLowerCase().includes('startup')) {
                            tempStartup.push(post);
                        }
                    }
                }
                this.newsList.next(tempNews);
                this.startupList.next(tempStartup);
            })
            .catch(error => {
                console.error(error);
            });
    }

    getNewsList() {
        return this.newsList.asObservable();
    }

    getStartupList() {
        return this.startupList.asObservable();
    }
    
    mapNews(data: any[]): Post[] {
        return MAPPED_RESPONSE_TO_POST_ARRAY; // logic to convert axios response to Post array
    }

}

The above service is called by the constructor of home component.上述服务是由 home 组件的构造函数调用的。

import { Component, ViewEncapsulation } from '@angular/core';
import { Post } from '../../@core/mock/post.model';
import { APIService } from '../../@core/services/API.service';

@Component({
  selector: 'ngx-editors',
  encapsulation: ViewEncapsulation.None,
  styleUrls: ['./home.component.scss'],
  templateUrl: './home.component.html',
})
export class HomeComponent {
  newsList: Post[];
  startupList: Post[];
  constructor(private api: APIService) {
    this.newsList = [];
    this.startupList = [];
    let i = 0;
    api.getNewsList().subscribe(
      (value) => {
        console.log('onHomeNews:');
        console.log(value);
        console.log(this.startupList);
        if (value != null) {
          for (const post of value) {
            if (i < 4) {
              this.newsList.push(post);
              i++;
            }
          }
        }
      },
      (error) => {
        console.log(error);
      },
      () => {
        console.log('onComplete:');
    });

    i = 0;
    api.getStartupList().subscribe(
      (value) => {
        console.log('onHomeStartup:');
        console.log(value);
        console.log(this.startupList);
          for (const post of value) {
            if (i < 4) {
              this.startupList.push(post);
              i++;
            }
        }
      },
      (error) => {
        console.log(error);
      },
      () => {
        console.log('onComplete:');
    });
  }
}

The problem is that I am getting newsList when the response comes from the API but no value is change is detected for startupList.问题是当响应来自 API 但没有检测到启动列表的值更改时,我正在获取新闻列表。 I am getting response on tempStartup that means the API is sending data.我在 tempStartup 上收到响应,这意味着 API 正在发送数据。
Edit 1编辑 1
I have another component called startup where also I have subscribed to getStartupList().我有另一个名为启动的组件,我也订阅了 getStartupList()。 When I switch to that component and come back to home component the startupList gets updated.当我切换到该组件并返回主组件时,startupList 会更新。 Here are the logs before switching to the startup component.这是切换到启动组件之前的日志。

sub-header.component.ts:86 home
home.component.ts:40 onHomeNews:
home.component.ts:41 null
home.component.ts:42 []
home.component.ts:62 onHomeStartup:
home.component.ts:63 null
home.component.ts:64 []
home.component.ts:40 onHomeNews:
home.component.ts:41 (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
home.component.ts:42 []

Logs after switching to startup component and coming back to home component.切换到启动组件并返回主组件后的日志。

sub-header.component.ts:86 home
home.component.ts:40 onHomeNews:
home.component.ts:41 null
home.component.ts:42 []
home.component.ts:62 onHomeStartup:
home.component.ts:63 null
home.component.ts:64 []
home.component.ts:40 onHomeNews:
home.component.ts:41 (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
home.component.ts:42 []
sub-header.component.ts:86 startup
sub-header.component.ts:86 home
home.component.ts:40 onHomeNews:
home.component.ts:41 (8) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
home.component.ts:42 []
home.component.ts:62 onHomeStartup:
home.component.ts:63 (5) [{…}, {…}, {…}, {…}, {…}]
home.component.ts:64 []

PS getAllPost() is called from app.component.ts so that its called as soon as the app is created. PS getAllPost() 从 app.component.ts 调用,以便在创建应用程序后立即调用它。

The Angular renderer does not know the list has been updated when push to the array. Angular 渲染器在push送到数组时不知道列表已更新。 The underlying reference to the array hasn't changed, so it won't re-render the template.对数组的底层引用没有改变,所以它不会重新渲染模板。

Instead you could reassign the variable holding the array using the spread operator.相反,您可以使用扩展运算符重新分配保存数组的变量。

export class HomeComponent {
  ...

  constructor(private api: APIService) {
    this.newsList = [];
    this.startupList = [];
    let i = 0;
    api.getNewsList().subscribe(
      (value) => {
        ...
              this.newList = [...this.newsList, post];        // <-- reassign using spread operator
        ...
      },
      ...
    );

    i = 0;
    api.getStartupList().subscribe(
        ...
            this.startupList = [...this.startupList, post];   // <-- reassign using spread operator
        ...
      },
    );
  }
}

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

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