我正在开发一个 Angular 项目,但遇到以下问题。
基本上我有这个HomeComponent视图代码:
<div class="courses-panel">
<h3>All Courses</h3>
<mat-tab-group>
<mat-tab label="Beginners">
<courses-card-list [courses]="beginnerCourses$ | async"></courses-card-list>
</mat-tab>
<mat-tab label="Advanced">
<courses-card-list [courses]="advancedCourses$ | async"></courses-card-list>
</mat-tab>
</mat-tab-group>
</div>
下面是相关的 TypeScript 代码:
import {Component, OnInit} from '@angular/core';
import {Course, sortCoursesBySeqNo} from '../model/course';
import {interval, noop, Observable, of, throwError, timer} from 'rxjs';
import {catchError, delay, delayWhen, filter, finalize, map, retryWhen, shareReplay, tap} from 'rxjs/operators';
import {HttpClient} from '@angular/common/http';
import {MatDialog, MatDialogConfig} from '@angular/material/dialog';
import {CourseDialogComponent} from '../course-dialog/course-dialog.component';
import { CoursesService } from '../services/courses.service';
@Component({
selector: 'home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
beginnerCourses$: Observable<Course[]>;
advancedCourses$: Observable<Course[]>;
constructor(private coursesService: CoursesService) {
}
ngOnInit() {
const courses$ = this.coursesService.loadedAllCourses()
.pipe(
map(courses => courses.sort(sortCoursesBySeqNo))
)
this.beginnerCourses$ = courses$
.pipe(
map(courses => courses.filter(course => course.category == "BEGINNER"))
);
this.advancedCourses$ = courses$
.pipe(
map(courses => courses.filter(course => course.category == "ADVANCED"))
);
}
}
正如您在前面的代码中看到的组件初始化首先我使用服务类的loadedAllCourses()方法检索一个Observable(它只是向API 执行一个HTTP 请求),然后从这个Observable 我创建另外两个Observable,它们是beginCourses $和advancedCourses$包含两种不同类型的课程过滤检索到的课程 Observable。
在我的HomeCompoent视图中,我声明了 只显示课程信息的课程卡列表组件,如下所示:
<courses-card-list [courses]="beginnerCourses$ | async"></courses-card-list>
和:
<courses-card-list [courses]="advancedCourses$ | async"></courses-card-list>
这是课程卡列表组件的视图代码:
<mat-card *ngFor="let course of (courses | async)" class="course-card mat-elevation-z10">
<mat-card-header>
<mat-card-title>{{course.description}}</mat-card-title>
</mat-card-header>
<img mat-card-image [src]="course.iconUrl">
<mat-card-content>
<p>{{course.longDescription}}</p>
</mat-card-content>
<mat-card-actions class="course-actions">
<button mat-button class="mat-raised-button mat-primary" [routerLink]="['/courses', course.id]">
VIEW COURSE
</button>
<button mat-button class="mat-raised-button mat-accent"
(click)="editCourse(course)">
EDIT
</button>
</mat-card-actions>
</mat-card>
这是相关的后端代码:
import { Component, OnInit, Input } from '@angular/core';
import { Course } from '../model/course';
import { MatDialogConfig, MatDialog } from '@angular/material/dialog';
import { CourseDialogComponent } from '../course-dialog/course-dialog.component';
@Component({
selector: 'courses-card-list',
templateUrl: './courses-card-list.component.html',
styleUrls: ['./courses-card-list.component.scss']
})
export class CoursesCardListComponent implements OnInit {
@Input()
courses: Course[] = [];
constructor(private dialog: MatDialog) { }
ngOnInit() {
}
editCourse(course: Course) {
const dialogConfig = new MatDialogConfig();
dialogConfig.disableClose = true;
dialogConfig.autoFocus = true;
dialogConfig.width = "400px";
dialogConfig.data = course;
const dialogRef = this.dialog.open(CourseDialogComponent, dialogConfig);
}
}
问题是在运行我的应用程序时,我收到以下似乎与两个异步管道相关的错误消息:
core.js:4081 ERROR Error: InvalidPipeArgument: '[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]' for pipe 'AsyncPipe'
at invalidPipeArgumentError (common.js:4148)
at AsyncPipe._selectStrategy (common.js:4250)
at AsyncPipe._subscribe (common.js:4240)
at AsyncPipe.transform (common.js:4228)
at Module.ɵɵpipeBind1 (core.js:24409)
at CoursesCardListComponent_Template (courses-card-list.component.html:1)
at executeTemplate (core.js:7329)
at refreshView (core.js:7198)
at refreshComponent (core.js:8335)
at refreshChildComponents (core.js:6991)
defaultErrorLogger @ core.js:4081
handleError @ core.js:4129
(anonymous) @ core.js:28062
invoke @ zone-evergreen.js:364
run @ zone-evergreen.js:123
runOutsideAngular @ core.js:27065
tick @ core.js:28062
(anonymous) @ core.js:27941
invoke @ zone-evergreen.js:364
onInvoke @ core.js:27138
invoke @ zone-evergreen.js:363
run @ zone-evergreen.js:123
run @ core.js:27020
next @ core.js:27940
schedulerFn @ core.js:24535
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:24525
checkStable @ core.js:27074
onLeave @ core.js:27184
onInvokeTask @ core.js:27132
invokeTask @ zone-evergreen.js:398
runTask @ zone-evergreen.js:167
invokeTask @ zone-evergreen.js:480
invokeTask @ zone-evergreen.js:1621
globalZoneAwareCallback @ zone-evergreen.js:1658
load (async)
customScheduleGlobal @ zone-evergreen.js:1773
scheduleTask @ zone-evergreen.js:385
onScheduleTask @ zone-evergreen.js:272
scheduleTask @ zone-evergreen.js:378
scheduleTask @ zone-evergreen.js:210
scheduleEventTask @ zone-evergreen.js:236
(anonymous) @ zone-evergreen.js:1928
(anonymous) @ http.js:1764
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
subscribeToResult @ subscribeToResult.js:9
_innerSub @ mergeMap.js:59
_tryNext @ mergeMap.js:53
_next @ mergeMap.js:36
next @ Subscriber.js:49
(anonymous) @ subscribeToArray.js:3
_trySubscribe @ Observable.js:42
subscribe @ Observable.js:28
call @ mergeMap.js:21
subscribe @ Observable.js:23
call @ filter.js:13
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
shareReplayOperation @ shareReplay.js:28
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
call @ map.js:16
subscribe @ Observable.js:23
createSubscription @ common.js:4160
_subscribe @ common.js:4241
transform @ common.js:4228
ɵɵpipeBind1 @ core.js:24409
HomeComponent_Template @ home.component.html:9
executeTemplate @ core.js:7329
refreshView @ core.js:7198
refreshComponent @ core.js:8335
refreshChildComponents @ core.js:6991
refreshView @ core.js:7248
refreshEmbeddedViews @ core.js:8289
refreshView @ core.js:7222
refreshComponent @ core.js:8335
refreshChildComponents @ core.js:6991
refreshView @ core.js:7248
renderComponentOrTemplate @ core.js:7312
tickRootContext @ core.js:8507
detectChangesInRootView @ core.js:8532
detectChanges @ core.js:9918
tick @ core.js:28052
(anonymous) @ core.js:27941
invoke @ zone-evergreen.js:364
onInvoke @ core.js:27138
invoke @ zone-evergreen.js:363
run @ zone-evergreen.js:123
run @ core.js:27020
next @ core.js:27940
schedulerFn @ core.js:24535
__tryOrUnsub @ Subscriber.js:183
next @ Subscriber.js:122
_next @ Subscriber.js:72
next @ Subscriber.js:49
next @ Subject.js:39
emit @ core.js:24525
checkStable @ core.js:27074
onHasTask @ core.js:27152
hasTask @ zone-evergreen.js:419
_updateTaskCount @ zone-evergreen.js:440
_updateTaskCount @ zone-evergreen.js:263
runTask @ zone-evergreen.js:184
drainMicroTaskQueue @ zone-evergreen.js:569
Promise.then (async)
scheduleMicroTask @ zone-evergreen.js:552
scheduleTask @ zone-evergreen.js:388
scheduleTask @ zone-evergreen.js:210
scheduleMicroTask @ zone-evergreen.js:230
scheduleResolveOrReject @ zone-evergreen.js:847
then @ zone-evergreen.js:979
bootstrapModule @ core.js:27726
./src/main.ts @ main.ts:13
__webpack_require__ @ bootstrap:78
0 @ main.ts:14
__webpack_require__ @ bootstrap:78
checkDeferredModules @ bootstrap:44
webpackJsonpCallback @ bootstrap:31
(anonymous) @ main.js:1
Show 72 more frames
core.js:4081 ERROR Error: InvalidPipeArgument: '[object Object],[object Object],[object Object]' for pipe 'AsyncPipe'
at invalidPipeArgumentError (common.js:4148)
at AsyncPipe._selectStrategy (common.js:4250)
at AsyncPipe._subscribe (common.js:4240)
at AsyncPipe.transform (common.js:4228)
at Module.ɵɵpipeBind1 (core.js:24409)
at CoursesCardListComponent_Template (courses-card-list.component.html:1)
at executeTemplate (core.js:7329)
at refreshView (core.js:7198)
at refreshComponent (core.js:8335)
at refreshChildComponents (core.js:6991)
怎么了?我错过了什么?我该如何解决这个问题?
EDIT-1 : * 这是我的服务类代码:
@Injectable({
providedIn: 'root'
})
export class CoursesService {
constructor(private http:HttpClient) {}
loadedAllCourses(): Observable<Course[]> {
// The obsarvable return a JSON containing the "payload" property containing the array
//return this.http.get<Course[]>("/api/courses");
return this.http.get<Course[]>("/api/courses")
.pipe(
map(res => res["payload"]),
/* Keep the result of this HTTP request in memory avoiding that n async pipe or subscription
will cause n call to the API. Keep the result in memory and share between subsequence subscriber */
shareReplay()
);
}
}
如您所见,loadedAllCourses()方法返回一个 Observable,因此我使用异步管道将其“订阅”到 HomeComponent 中,以检索我试图传递给子组件的课程数组