[英]Angular: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
[英]Angular 11 error: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable
我知道具有類似標題/問題的問題的數量:我花了一天半的時間閱讀並嘗試了可能的解決方案,但沒有成功。 我的情況有點不同,我的 Angular 版本較新。
我有一個帶有圖表的頁面(chart.js 到 ng2-charts),我想對其數據進行分頁。 這是它的外觀,包括控件:
<div class="paginable-area" [class.loading]="chartLoading">
<app-line-chart *ngIf="!tableError" [lineChartData]="chartData" [lineChartLabels]="chartLabels"></app-line-chart>
<div class="page-controls">
<button class="button" (click)="previousChartPage()" [disabled]="currentChartPage <= 1">◀</button>
<button class="button" (click)="nextChartPage()">▶</button>
</div>
</div>
當頁面加載時,第一頁正確顯示並且看起來不錯。 但是,一旦我按下按鈕以獲取不同的頁面,我就會在控制台中收到以下錯誤:
TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
RxJS 13
Angular 16
RxJS 30
getAggregates dashboard.component.ts:144
nextChartPage dashboard.component.ts:92
DashboardComponent_Template_button_click_9_listener dashboard.component.html:10
Angular 22
DashboardComponent_Template dashboard.component.html:10
Angular 13
RxJS 3
按下一頁按鈕,這些是按順序調用的方法:
public nextChartPage() : void {
this.currentChartPage += 1;
this.getAggregates();
}
// ...
private getAggregates() : void {
this.chartLoading = true;
this.statsService.getAggregateStats(this.currentChartPage)
.pipe(
toArray(),
catchError((error) => {
this.chartError = `An error occurred: ${error.toString()}`;
return of(error);
}),
map(aggregates => {
const data = {
labels: [] as string[],
successful: [] as number[],
unsuccessful: [] as number[],
};
aggregates.forEach((agg: DataAggregate) => {
data.labels.push(agg.date);
data.successful.push(agg.successful);
data.unsuccessful.push(agg.unsuccessful);
});
this.chartLabels = data.labels;
if (typeof this.chartData[0].data !== "undefined" && typeof this.chartData[1].data !== "undefined") {
this.chartData[0].data = data.successful;
this.chartData[1].data = data.unsuccessful;
}
this.chartLoading = false;
return data;
})
)
.subscribe();
}
// ...
// statsService.getAggregateStats, the function that makes the HTTP GET request :
public getAggregateStats(page: number = 1) : Observable<DataAggregate> {
return this.http.get<DataAggregateResponseItem[]>(
`https://my-api.xxx/stats?page=${page}`,
).pipe(
mergeAll(),
map((r: DataAggregateResponseItem) => {
const thing: DataAggregate = {
date: r.day,
successful: parseInt(r.successful),
unsuccessful: parseInt(r.unsuccessful),
};
console.log(`${JSON.stringify(thing)}`);
return thing;
}),
);
}
如您所見,每次請求圖表頁面時都會調用getAggregates()
方法,包括首次加載圖表時。 第一次調用成功,但第二次調用顯示錯誤(我還嘗試增加頁面計數器並在頁面加載時再次調用它而不是等待按下按鈕:相同的結果),並且任何后續調用都以一個空的 object。
我有一個表格,其中包含來自相同 api 的數據,在同一頁面上以完全相同的方式分頁,但它可以完美地工作。 數據當然有不同的形狀,所以問題無疑是在 map() 中的某個地方,但我就是想不通。
of()
,但這只會導致東西作為 Observables of Observables 出現......我對 Angular 和 rxjs 還是比較陌生,所以很可能我做錯了什么,但我不知道是什么。 請幫忙。
編輯:將服務方法(上面代碼中顯示的最后一個)更改為:
public getAggregateStats(page: number = 1) : Observable<DataAggregate> {
return this.http.get<DataAggregateResponseItem[]>(
`https://my-api.xxx/stats?page=${page}`,
).pipe(
map((r: DataAggregateResponseItem[]) => {
return r.map((agg) => {
return {
date: agg.day,
successful: parseInt(agg.successful),
unsuccessful: parseInt(agg.unsuccessful),
} as DataAggregate;
});
}),
mergeAll(),
);
}
發生了一些變化:當我加載圖表的下一頁時,錯誤是:
TypeError: r.map is not a function
getAggregateStats stats.service.ts:75
RxJS 9
Angular 16
RxJS 28
getAggregates dashboard.component.ts:143
nextChartPage dashboard.component.ts:92
DashboardComponent_Template_button_click_9_listener dashboard.component.html:10
Angular 22
DashboardComponent_Template dashboard.component.html:10
Angular 13
RxJS 3
這讓我覺得 pipe 最初是按預期接收數據的,但是當再次調用該方法時,它反而得到了一些不是數組的東西(因此它沒有 map 方法)。 但是如果我查看控制台,我可以清楚地看到第二個請求成功了,甚至包含了正確的內容!
// First request, when the page loads:
GET https://my-api.xxx/stats?page=1 [HTTP/1.1 200 OK 249ms]
[{"successful":"1","unsuccessful":"1","day":"2020-12-15"},{"successful":"1","unsuccessful":"0","day":"2020-12-14"}]
// Second request, when I request the next page
GET https://my-api.xxx/stats?page=2 [HTTP/1.1 200 OK 249ms]
{"2":{"successful":"2","unsuccessful":"1","day":"2020-12-11"},"3":{"successful":"3","unsuccessful":"6","day":"2020-12-10"}}
我只是想通了,最后這個問題與 Angular 或 Typescript 完全無關(盡管錯誤消息對於查明原因並不完全有用)。
我得到結果的 API 是用 Laravel (PHP) 制作的,結果證明雖然第一頁以以下形式返回:
[
"0" => ["some" => "data"],
"1" => ["some" => "more data"],
]
轉換為 JSON 為:
[
{"some": "data"},
{"some": "more data"}
]
PHP 一側的第二頁和后續頁面如下所示:
[
"2" => ["some" => "data"],
"3" => ["some" => "more data"],
]
從表面上看,這似乎是有序的:索引正在上升,因為正在返回后續項目。 但這導致 Laravel 的 whatchamacallit 它用於將數組轉換為 JSON 來解釋前面的內容:
{
"2": {"some": "data"},
"3": {"some": "more data"}
}
這當然完全拋棄了 Angular。
我向所有不得不閱讀所有這些廢話的人道歉。 我至少吸取了教訓:永遠不要相信 PHP。
我多次遇到此類問題, ngIf
救了我。 將數據傳遞給圖表。
<app-line-chart *ngIf="!tableError && chartData.length > 0" [lineChartData]="chartData" [lineChartLabels]="chartLabels"></app-line-chart>
對我來說,問題是獲取請求所在的 http api 失敗了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.