处理来自 Angular 中相同 API 的多种响应类型
Handling multiple response types from same API in Angular
我是 Angular 的新手。我一直在开发一项服务,该服务从 API 和 return 中获取某些数据。 API 可以 return 两种类型的 JSON 响应,自定义数据类型数组或自定义错误代码和消息,以防服务器出现内部错误。根据两种可能的响应,我创建了两个接口,比如 I1
和 I2
。 API 编辑的 JSON 响应 return 也分别遵循相同的结构。
interface I1 {
responseData: customData[]
}
interface I2 {
errorCode: number,
errorMessage: string
}
对于服务本身,我想编写一个函数,它首先获取数据并检查接收到的类型。如果类型是 I1
,那么它将 return I1
中数组的可观察对象,或者如果类型是 I2
,那么它将在控制台上记录错误,并且return 错误对象。我在服务中写了一个函数 class:
APIResponse: I1 | I2;
getData(): Observable<CustomData[] | I2> {
this.http.get<I1 | I2>('url/to/api').subscribe(res => {
this.APIResponse = res;
});
if('errorCode' in this.APIResponse) {
console.log(this.APIResponse.errorCode);
return of(this.APIResponse);
}
else if('responseData' in APIResponse) {
return of(this.APIResponse.responseData);
}
}
现在此代码在编译时显示错误,因为 this.APIResponse
的类型与其 return 值的函数预期的类型不同。我可以将函数的 return 类型更改为 Observable<I1 | I2>
,但我将无法仅 return 数组。我无法以任何方式更改 API 结构。我曾尝试将 APIResponse 分配给 I2
类型的中间变量,然后从函数中 return 分配它,但它不允许我分配类型 'I1 | I2'
到类型 'I2'
。
我应该如何从这里开始才能得到想要的结果?
将您的 getData 方法更改为:-
getData(): Observable<CustomData[] | I2> {
return this.http.get('url/to/api').pipe(map((res : I1|I2) => {
if('errorCode' in res) {
this.APIResponse = res;
console.log(this.APIResponse.errorCode);
return res;
} else {
this.APIResponse = res;
return res.responseData;
}
}));
}
任何你想使用这个方法的地方,像这样使用它:-
getData().subscribe((res) => console.log(res));
我不确定您为什么订阅服务,但这是反模式。
如果 APIResponse
变量仅在 getData()
函数中使用,只是为了创建一个新的可观察对象,那么您不需要它。
要记录响应或执行任何副作用,请使用 tap
运算符。
getData(): Observable<CustomData[] | I2> {
return this.http.get<I1 | I2>('url/to/api').pipe(
map(res => {
if ('responseData' in res) {
return res.responseData;
} else if ('errorCode' in res) {
return res;
}
}),
tap(res => {
// Side effects
if ('errorCode' in res) {
console.log(res.errorCode);
}
}),
);
}
如果您正在使用 APIResponse
变量并想为其分配响应,则必须在 tap
运算符中执行此操作,因为这是副作用。
tap(res => {
// Assign value to APIResponse;
this.APIResponse = res;
})
最后,要从服务器获取数据,请在您的组件中订阅 getData()
可观察流。
this._service.getData().subscribe(data => { // do what you want with data })
如果您的服务使用 2xx
以外的代码发送错误响应,那么您可以使用 catchError
运算符或使用 http 选项来完全控制请求。
我是 Angular 的新手。我一直在开发一项服务,该服务从 API 和 return 中获取某些数据。 API 可以 return 两种类型的 JSON 响应,自定义数据类型数组或自定义错误代码和消息,以防服务器出现内部错误。根据两种可能的响应,我创建了两个接口,比如 I1
和 I2
。 API 编辑的 JSON 响应 return 也分别遵循相同的结构。
interface I1 {
responseData: customData[]
}
interface I2 {
errorCode: number,
errorMessage: string
}
对于服务本身,我想编写一个函数,它首先获取数据并检查接收到的类型。如果类型是 I1
,那么它将 return I1
中数组的可观察对象,或者如果类型是 I2
,那么它将在控制台上记录错误,并且return 错误对象。我在服务中写了一个函数 class:
APIResponse: I1 | I2;
getData(): Observable<CustomData[] | I2> {
this.http.get<I1 | I2>('url/to/api').subscribe(res => {
this.APIResponse = res;
});
if('errorCode' in this.APIResponse) {
console.log(this.APIResponse.errorCode);
return of(this.APIResponse);
}
else if('responseData' in APIResponse) {
return of(this.APIResponse.responseData);
}
}
现在此代码在编译时显示错误,因为 this.APIResponse
的类型与其 return 值的函数预期的类型不同。我可以将函数的 return 类型更改为 Observable<I1 | I2>
,但我将无法仅 return 数组。我无法以任何方式更改 API 结构。我曾尝试将 APIResponse 分配给 I2
类型的中间变量,然后从函数中 return 分配它,但它不允许我分配类型 'I1 | I2'
到类型 'I2'
。
我应该如何从这里开始才能得到想要的结果?
将您的 getData 方法更改为:-
getData(): Observable<CustomData[] | I2> {
return this.http.get('url/to/api').pipe(map((res : I1|I2) => {
if('errorCode' in res) {
this.APIResponse = res;
console.log(this.APIResponse.errorCode);
return res;
} else {
this.APIResponse = res;
return res.responseData;
}
}));
}
任何你想使用这个方法的地方,像这样使用它:-
getData().subscribe((res) => console.log(res));
我不确定您为什么订阅服务,但这是反模式。
如果 APIResponse
变量仅在 getData()
函数中使用,只是为了创建一个新的可观察对象,那么您不需要它。
要记录响应或执行任何副作用,请使用 tap
运算符。
getData(): Observable<CustomData[] | I2> {
return this.http.get<I1 | I2>('url/to/api').pipe(
map(res => {
if ('responseData' in res) {
return res.responseData;
} else if ('errorCode' in res) {
return res;
}
}),
tap(res => {
// Side effects
if ('errorCode' in res) {
console.log(res.errorCode);
}
}),
);
}
如果您正在使用 APIResponse
变量并想为其分配响应,则必须在 tap
运算符中执行此操作,因为这是副作用。
tap(res => {
// Assign value to APIResponse;
this.APIResponse = res;
})
最后,要从服务器获取数据,请在您的组件中订阅 getData()
可观察流。
this._service.getData().subscribe(data => { // do what you want with data })
如果您的服务使用 2xx
以外的代码发送错误响应,那么您可以使用 catchError
运算符或使用 http 选项来完全控制请求。