问题描述
我正在创建一个有 API 服务的 Angular 应用程序。此服务使用 axios 调用 API 并根据需要更新 BehaviorSubject 的值,这里是该代码。
export const getStaticProps = async () => {
let posts = []
try
{
// await the promise
const querySnapshot = await firebase
.firestore()
.collection('posts')
.orderBy('createdAt','desc')
.get();
// "then" part after the await
querySnapshot.forEach(function (doc) {
console.log(doc.data().title)
console.log(doc.data().pid)
posts.push({
pid: doc.data().pid,title: doc.data().title,})
})
console.log(posts)
} catch(error) {
// catch part using try/catch
console.log('Error getting documents: ',error)
// return something else here,or an empty props,or throw an exception or whatever
}
return {
props: {
posts
}
}
}
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
}
}
问题是,当响应来自 API 时,我收到 newsList,但没有检测到 startupList 的值发生变化。我在 tempStartup 上收到响应,这意味着 API 正在发送数据。
@H_404_15@编辑 1
我有另一个名为 startup 的组件,其中我也订阅了 getStartupList()。当我切换到该组件并返回主组件时,startupList 会更新。这是切换到启动组件之前的日志。
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++;
}
}
},() => {
console.log('onComplete:');
});
}
}
切换到启动组件并返回主组件后登录。
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 []
@H_404[email protected]. getAllPost() 是从 app.component.ts 调用的,以便在创建应用程序后立即调用它。
解决方法
当 push
到数组时,Angular 渲染器不知道列表已更新。对数组的底层引用没有改变,所以它不会重新渲染模板。
相反,您可以使用扩展运算符重新分配保存数组的变量。
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
...
},);
}
}