向 http 请求添加查询参数时出错
Error when adding query params to http request
我正在使用英雄之旅示例中所示的模拟数据和 InMemoryDbService。当我不传递 HttpParams 时,加载数据工作正常。添加参数后,我会收到 500 响应,正文中包含以下错误:{error: "collection.filter is not a function"}
我已经使用 get 请求中的数据填充了我的 table,如下所示:
组件代码:
@Component({
selector: 'app-adapter',
templateUrl: './adapter.component.html',
styleUrls: ['./adapter.component.css']
})
export class AdapterComponent implements OnInit {
dataSource = new MatTableDataSource<Request>();
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
constructor(private api: BaseServiceApi) {}
ngOnInit() {
this.refresh(); // this works with no params and populates my table
}
refresh(params?) {
this.getRequests(params)
.subscribe(reply => {
this.dataSource.data = reply.payload as Request[];
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
this.pageSize = this.paginator.pageSize;
}
);
}
getRequests(params?): Observable<ServerReply> {
console.log(params);
return this.api.get("requests", params);
}
processSearch() { // here is where I am submitting a form and trying to get new response
if (this.searchForm.invalid)
return;
// these params are not fields of ServerReply or request but are filters
let params = new HttpParams({fromObject: this.searchForm.getRawValue()});
this.refresh(params); // this is submitting with params and throwing exception
}
}
api 服务:
import { Injectable } from '@angular/core';
import {Observable, of, pipe} from "rxjs";
import {HttpClient, HttpParams} from "@angular/common/http";
import {catchError} from "rxjs/operators";
import {ServerReply} from "../../models/server-reply";
@Injectable({
providedIn: 'root'
})
export class BaseServiceApi {
apiUrl: string;
constructor(private http: HttpClient) {
}
get(path: string, params?: HttpParams): Observable<ServerReply> {
return this.http.get<ServerReply>(this.apiUrl + path, {params})
//.pipe(catchError(this.handleError<ServerReply>(path, new ServerReply()))
//);
}
private handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
// TODO: send the error to remote logging infrastructure
console.error(operation + ": " + JSON.stringify(error)); // log to console instead
// Let the app keep running by returning an empty result.
return of(result as T);
};
}
}
服务器回复:
export class ServerReply {
alerts: [];
payload: [];
}
要求:
export class Request {
id: number,
// other fields omitted
}
模拟数据服务:
@Injectable({
providedIn: 'root'
})
export class MockDataService implements InMemoryDbService {
createDb() {
let requests = this.createRequests(1000);
return {requests};
}
private createCloudRequests(count: number) {
// returns one ServerReply with a Request[] in ServerReply.payload
}
}
不确定我做错了什么。我尝试在英雄之旅示例中添加查询参数并且有效(即使英雄的不存在字段也不会像这样出错)。
应用模块导入:
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
MaterialModule,
AppRoutingModule,
HttpClientModule,
HttpClientInMemoryWebApiModule.forRoot(MockDataService, {dataEncapsulation: false}),
ReactiveFormsModule,
]
问题是默认情况下,InMemoryDbSerivce 期望 db 对象中的所有内容都是一个数组。它只会尝试根据我的查询参数应用过滤器。
我通过查看 github 中的示例找到了解决方案:https://github.com/angular/in-memory-web-api/blob/master/src/app/hero-in-mem-data-override.service.ts
在这里我能够拦截获取请求并使用我提供的查询参数应用我自己的过滤
模拟服务:
import {InMemoryDbService, RequestInfo, STATUS} from 'angular-in-memory-web-api';
@Injectable({
providedIn: 'root'
})
export class MockDataService implements InMemoryDbService {
...
// intercept get method for all in memory requests.
get(reqInfo: RequestInfo) {
let queryParams: Map<string, string[]> = reqInfo.query;
console.log(queryParams);
if (queryParams.size > 0) // if no params are passed, Map exists but is empty
return this.handleFilterRequest(reqInfo, queryParams); // custom Response built here
// return request as passthrough if no params
return undefined;
}
}
我正在使用英雄之旅示例中所示的模拟数据和 InMemoryDbService。当我不传递 HttpParams 时,加载数据工作正常。添加参数后,我会收到 500 响应,正文中包含以下错误:{error: "collection.filter is not a function"}
我已经使用 get 请求中的数据填充了我的 table,如下所示:
组件代码:
@Component({
selector: 'app-adapter',
templateUrl: './adapter.component.html',
styleUrls: ['./adapter.component.css']
})
export class AdapterComponent implements OnInit {
dataSource = new MatTableDataSource<Request>();
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
constructor(private api: BaseServiceApi) {}
ngOnInit() {
this.refresh(); // this works with no params and populates my table
}
refresh(params?) {
this.getRequests(params)
.subscribe(reply => {
this.dataSource.data = reply.payload as Request[];
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
this.pageSize = this.paginator.pageSize;
}
);
}
getRequests(params?): Observable<ServerReply> {
console.log(params);
return this.api.get("requests", params);
}
processSearch() { // here is where I am submitting a form and trying to get new response
if (this.searchForm.invalid)
return;
// these params are not fields of ServerReply or request but are filters
let params = new HttpParams({fromObject: this.searchForm.getRawValue()});
this.refresh(params); // this is submitting with params and throwing exception
}
}
api 服务:
import { Injectable } from '@angular/core';
import {Observable, of, pipe} from "rxjs";
import {HttpClient, HttpParams} from "@angular/common/http";
import {catchError} from "rxjs/operators";
import {ServerReply} from "../../models/server-reply";
@Injectable({
providedIn: 'root'
})
export class BaseServiceApi {
apiUrl: string;
constructor(private http: HttpClient) {
}
get(path: string, params?: HttpParams): Observable<ServerReply> {
return this.http.get<ServerReply>(this.apiUrl + path, {params})
//.pipe(catchError(this.handleError<ServerReply>(path, new ServerReply()))
//);
}
private handleError<T>(operation = 'operation', result?: T) {
return (error: any): Observable<T> => {
// TODO: send the error to remote logging infrastructure
console.error(operation + ": " + JSON.stringify(error)); // log to console instead
// Let the app keep running by returning an empty result.
return of(result as T);
};
}
}
服务器回复:
export class ServerReply {
alerts: [];
payload: [];
}
要求:
export class Request {
id: number,
// other fields omitted
}
模拟数据服务:
@Injectable({
providedIn: 'root'
})
export class MockDataService implements InMemoryDbService {
createDb() {
let requests = this.createRequests(1000);
return {requests};
}
private createCloudRequests(count: number) {
// returns one ServerReply with a Request[] in ServerReply.payload
}
}
不确定我做错了什么。我尝试在英雄之旅示例中添加查询参数并且有效(即使英雄的不存在字段也不会像这样出错)。
应用模块导入:
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
MaterialModule,
AppRoutingModule,
HttpClientModule,
HttpClientInMemoryWebApiModule.forRoot(MockDataService, {dataEncapsulation: false}),
ReactiveFormsModule,
]
问题是默认情况下,InMemoryDbSerivce 期望 db 对象中的所有内容都是一个数组。它只会尝试根据我的查询参数应用过滤器。
我通过查看 github 中的示例找到了解决方案:https://github.com/angular/in-memory-web-api/blob/master/src/app/hero-in-mem-data-override.service.ts
在这里我能够拦截获取请求并使用我提供的查询参数应用我自己的过滤
模拟服务:
import {InMemoryDbService, RequestInfo, STATUS} from 'angular-in-memory-web-api';
@Injectable({
providedIn: 'root'
})
export class MockDataService implements InMemoryDbService {
...
// intercept get method for all in memory requests.
get(reqInfo: RequestInfo) {
let queryParams: Map<string, string[]> = reqInfo.query;
console.log(queryParams);
if (queryParams.size > 0) // if no params are passed, Map exists but is empty
return this.handleFilterRequest(reqInfo, queryParams); // custom Response built here
// return request as passthrough if no params
return undefined;
}
}