我的应用程序需要发出许多api请求(大约500个)并显示数据。当请求完成时,它需要显示结果。到目前为止,我已将其设置为使用带有可观察对象的异步管道。
我尝试将ChangeDetectorRef.detectChanges()放入complete()函数调用中。但是视图并没有受到任何影响。
news.component.ts
export class NewsComponent implements OnInit {
news: Observable<News[]>;
temp: News[] = new Array();
constructor(private dataService: DataService, private ref: ChangeDetectorRef) {
}
ngOnInit() {
this.news = this.getData();
}
getData(): Observable<News[]> {
let newsArr = new Subject<News[]>();
this.dataService.getTopNews().subscribe(val => {
this.temp.push(val);
newsArr.next(this.temp);
}, null, () => {
newsArr.complete();
this.ref.detectChanges();
console.log(this.news); //print all fetched data
});
return newsArr.asObservable();
}
}
news.component.html
<app-news-item *ngFor="let newsItem of news | async" [news]="newsItem">
</app-news-item>
news-item.component.ts
@Component({
selector: 'app-news-item',
templateUrl: './news-item.component.html',
styleUrls: ['./news-item.component.css']
})
export class NewsItemComponent implements OnInit {
@Input() news: Subject<News>;
constructor() { }
ngOnInit() {
}
}
视图(html)仅更新一次,开始时仅更新一些数据。数据正在正确加载,并且在提取所有数据后也会触发complete()。
答案 0 :(得分:2)
之所以不起作用,是因为您似乎将一个数组推入了临时数组,所以它实际上是一个数组数组...您可以像修复它一样简单
this.temp.push(...val)
不过,我可能会误解getTopNews
实际发出的信息(数组或单个新闻项)
但是,我建议尝试使用某些运算符来正确执行此操作,尤其是累积数据的扫描运算符,因为我假设getTopNews
发出多个“块”
import {scan} from 'rxjs/operators';
getData(): Observable<News[]> {
return this.dataService.getTopNews().pipe(
scan((acc, curr) => acc.concat(curr), []) // or acc.concat([curr]) if curr is actually a single news item and not an array
// if you're not sure if its a single or array:
// acc.concat(Array.isArray(curr) ? curr : [curr])
);
}
}
这是一个简单得多的结构,不需要temp变量或内部主题。如果您只希望它在全部完成后就呈现,那么只需将scan替换为reduce。
您的新闻项目组件中似乎也有一个错误,因为它似乎期望新闻主题而不是实际新闻,而这正是根据其余代码得到的。
答案 1 :(得分:0)
因为您的应用程序发出了将近500个请求,并且您在所有请求完成后呈现了数据,所以我建议采用更明确的方法,例如不使用异步管道。
export class NewsComponent implements OnInit, OnDestroy {
private unsub: Subscription;
news:News[] = [];
constructor(private dataService: DataService) {}
ngOnInit() {
this.getData();
}
getData(): Observable<News[]> {
const tmp: News[] = [];
this.unsub = this.dataService.getTopNews().subscribe(val => {
tmp.push(...val);
}, null, () => {
this.news = tmp;
console.log(this.news); //print all fetched data
});
}
ngOnDestroy() {
this.unsub.unsubscribe();
}
}
并在您的模板中
<app-news-item *ngFor="let newsItem of news" [news]="newsItem"></app-news-item>
答案 2 :(得分:0)
为什么事情太复杂了?只需将服务中的可观察对象放在组件上,然后使用异步管道进行订阅即可,它将负责订阅和取消订阅。
export class NewsComponent implements OnInit {
news = this.dataService.getTopNews();
constructor(private dataService: DataService) {
}
}