我正在创建一个有 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
}
}
}
上述服务由home组件的构造函数调用。
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 正在发送数据。
编辑 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++;
}
}
},
(error) => {
console.log(error);
},
() => {
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 []
P.S. getAllPost() 是从 app.component.ts 调用的,以便在创建应用程序后立即调用它。
答案 0 :(得分:0)
当 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
...
},
);
}
}