我认为最简单的解决方案是为您的响应创建一个包装器。
export interface BaySelectionResponse {
type: BayResponseType;
message: string;
bay: Bay;
}
export enum BayResponseType {
ERR = "Bay Error",
OK = "Success",
NOT_IN_LIST = "BAY NOT FOUND IN LIST"
}
通过这种方式,您可以适当地分离职责。
您的服务将根据响应分配状态和消息,您的页面可以决定如何实现显示结果。
使用这种方法,您甚至可以根据您的服务返回的任何状态,使用适当的模板将结果显示分成自己的组件。
示例
服务
首先,让我们创建一个服务,它的作用是检查我们的远程是否有可用数据:
@Injectable({providedIn: 'root'})
export class ApiLookupService {
}
首先,我们需要一个方法来简单地查询我们的遥控器以获取所有可能的值。我已经使用 rxjs of 函数 see here 模拟了这一点
mockNumbersEndpoint() {
return of([1, 3, 7, 9, 13])
}
其次,我们需要一个方法,该方法将接受来自消费者(即我们的路由组件,它将利用我们的服务)的输入,该方法可以检查针对给定输入值的响应。
checkValidity(input: number): Observable<ValidityResponseModel> {
// pipe the response from the api, and switch it into a ValidityResponseModel
return this.mockNumbersEndpoint().pipe(
switchMap(apiResponse => {
const validity = {} as ValidityResponseModel;
// check if the user's input is valid: Exists in response from server
if (apiResponse.some(number => input == number)) {
return of(this.createValidityResponse(
`Your chosen value ${input} is available`,
ValidityResponseTypes.SUCCESS,
input
));
}
// if our code reaches this point, it means we did not find the users input
return of(this.createValidityResponse(
`Your chosen value ${input} is NOT available`,
ValidityResponseTypes.INVALID,
input
));
}),
// we have now left the level of the 'switch' and are back in the pipe.
// We include catchError to handle if any error is thrown, such as network issues.
catchError(error => {
return of(this.createValidityResponse(
"Something went wrong with your request",
ValidityResponseTypes.ERR,
input
));
})
)
}
最后,我添加了一个实用函数,它将响应重组为ValidityResponseType
createValidityResponse(message: string, responseType: ValidityResponseTypes, response: number): ValidityResponseModel {
return {
message,
responseType,
response
} as ValidityResponseModel
}
完整的服务列表
@Injectable({providedIn: 'root'})
export class ApiLookupService {
mockNumbersEndpoint() {
return of([1, 3, 7, 9, 13])
}
checkValidity(input: number): Observable<ValidityResponseModel> {
return this.mockNumbersEndpoint().pipe(
switchMap(apiResponse => {
const validity = {} as ValidityResponseModel;
if (apiResponse.some(number => input == number)) {
return of(this.createValidityResponse(
`Your chosen value ${input} is available`,
ValidityResponseTypes.SUCCESS,
input
));
}
return of(this.createValidityResponse(
`Your chosen value ${input} is NOT available`,
ValidityResponseTypes.INVALID,
input
));
}),
catchError(error => {
return of(this.createValidityResponse(
"Something went wrong with your request",
ValidityResponseTypes.ERR,
input
));
})
)
}
createValidityResponse(message: string, responseType: ValidityResponseTypes, response: number): ValidityResponseModel {
return {
message,
responseType,
response
} as ValidityResponseModel
}
}
使用服务的组件
由于在最初的问题中,您在用户按 Enter 时执行检查,因此我选择实现一个表单。
组件
@Component({
templateUrl: './demo.component.html',
styleUrls: ['./demo.component.scss']
})
export class DemoComponent implements OnInit {
group: FormGroup;
responseType = ValidityResponseTypes;
validityResponse!: ValidityResponseModel;
constructor(private fb: FormBuilder, private service: ApiLookupService) {
this.group = fb.group({
input: fb.control(0, [Validators.minLength(1)])
})
}
ngOnInit(): void {
}
// ngSubmit.
formSubmittal() {
let v = this.group.get('input')?.value;
if (this.group.dirty && this.group.valid) {
this.group.reset();
this.checkValidity(v);
}
}
// pipe and take(1) to avoid having to manually unsubscribe.
checkValidity(num: number) {
this.service.checkValidity(num).pipe(take(1)).subscribe(responseFromApi => {
// logic based on response here
this.validityResponse = responseFromApi;
})
}
}
模板
<h2>demonstration</h2>
<div class="method">
<!-- ngSubmit will capture the Enter key event. -->
<form [formGroup]="group" (ngSubmit)="formSubmittal()">
<input type="number" formControlName="input">
</form>
</div>
<div class="result" [ngClass]="{'success': validityResponse?.responseType == responseType.SUCCESS, 'invalid': validityResponse?.responseType == responseType.INVALID}">
{{validityResponse?.message}}
</div>
一旦我们从服务中获得响应,我们就会根据响应类型设置样式,并在服务中显示为我们准备的消息。