Angular 根据RxJS HTTP请求中的用户输入检查对象数组中的对象是否存在

Angular 根据RxJS HTTP请求中的用户输入检查对象数组中的对象是否存在,angular,rxjs,rxjs6,rxjs-observables,rxjs-pipeable-operators,Angular,Rxjs,Rxjs6,Rxjs Observables,Rxjs Pipeable Operators,通过RxJS使用数据/动作流,如果用户输入了无效的间隔号,我想返回/传递一个错误。如果与用户输入的编号匹配,我的代码当前将返回一个间隔对象,但是如果用户输入的间隔列表中不存在的无效间隔编号,我不知道如何抛出错误 为了在多个组件/页面之间共享数据,我在BayService类中完成了大部分工作: ,但如何处理无效数字?例如,当用户在键入数字后按下submit按钮时,如何根据我的observable检查它是否无效,然后将某些内容返回到我的组件以显示在UI上?目前,我在客户端检查用户键入的内容,然后显示

通过RxJS使用数据/动作流,如果用户输入了无效的间隔号,我想返回/传递一个错误。如果与用户输入的编号匹配,我的代码当前将返回一个间隔对象,但是如果用户输入的间隔列表中不存在的无效间隔编号,我不知道如何抛出错误

  • 为了在多个组件/页面之间共享数据,我在BayService类中完成了大部分工作:
  • ,但如何处理无效数字?例如,当用户在键入数字后按下submit按钮时,如何根据我的observable检查它是否无效,然后将某些内容返回到我的组件以显示在UI上?目前,我在客户端检查用户键入的内容,然后显示错误,但我需要实际检查输入值是否确实存在于可观察对象中,如果不存在,则将错误或其他内容返回到bay.page.ts文件以在HTML中显示

    对不起,如果我没有很好地解释这一点,因为我正试图找出如何用词

    这是我的服务:


    这是我的Bay.page.ts:

    我认为最简单的解决方案是为您的响应创建一个包装器

    导出接口BaySelectionResponse{
    类型:BayResponseType;
    消息:字符串;
    海湾:海湾;;
    }
    导出枚举BayResponseType{
    ERR=“间隔错误”,
    OK=“成功”,
    NOT_IN_LIST=“列表中找不到间隔”
    }
    
    通过这种方式,您可以适当地分离责任

    您的服务将根据响应分配状态和消息,您的页面可以决定如何实现显示结果

    使用这种方法,您甚至可以根据服务返回的状态,使用适当的模板将结果显示分离到自己的组件中

    例子 服务 首先,让我们创建一个服务,该服务的作用是检查远程设备的可用数据:

    @Injectable({providedIn:'root'})
    导出类ApiLookupService{
    }
    
    首先,我们需要一个方法,该方法将简单地查询我们的远程所有可能的值。我已经用rxjs
    of
    函数模拟了这一点

    mockNumbersEndpoint(){
    返回([1,3,7,9,13])
    }
    
    其次,我们需要一种方法,它将接受来自消费者(即我们的路由组件,它将利用我们的服务)的输入,该方法可以根据给定的输入值检查响应

    checkValidity(输入:数字):可观察{
    //通过管道将来自api的响应转换为ValidityResponseModel
    返回此.mockNumbersEndpoint().pipe(
    开关映射(apiResponse=>{
    const validity={}作为ValidityResponseModel;
    //检查用户的输入是否有效:是否存在于服务器的响应中
    if(apiResponse.some(number=>input==number)){
    返回(this.createValidityResponse)(
    `您选择的值${input}可用`,
    ValidityResponseTypes.SUCCESS,
    输入
    ));
    }
    //如果我们的代码达到这一点,这意味着我们没有找到用户输入
    返回(this.createValidityResponse)(
    `您选择的值${input}不可用`,
    ValidityResponseTypes.INVALID,
    输入
    ));
    }),
    //我们现在已经离开了“开关”的高度,回到管道中。
    //如果抛出任何错误(如网络问题),我们将包括catchError来处理。
    catchError(错误=>{
    返回(this.createValidityResponse)(
    “您的请求出现问题”,
    ValidityResponseType.ERR,
    输入
    ));
    })
    )
    }
    
    最后,我添加了一个实用函数,它将响应重组为
    ValidityResponseType

    createValidityResponse(消息:string,responseType:ValidityResponseType,响应:number):ValidityResponseModel{
    返回{
    消息
    响应类型,
    响应
    }作为ValidityResponseModel
    }
    
    全套服务清单
    @Injectable({providedIn:'root'})
    导出类ApiLookupService{
    mockNumbersEndpoint(){
    返回([1,3,7,9,13])
    }
    检查有效性(输入:数字):可观察{
    返回此.mockNumbersEndpoint().pipe(
    开关映射(apiResponse=>{
    const validity={}作为ValidityResponseModel;
    if(apiResponse.some(number=>input==number)){
    返回(this.createValidityResponse)(
    `您选择的值${input}可用`,
    ValidityResponseTypes.SUCCESS,
    输入
    ));
    }
    返回(this.createValidityResponse)(
    `您选择的值${input}不可用`,
    ValidityResponseTypes.INVALID,
    输入
    ));
    }),
    catchError(错误=>{
    返回(this.createValidityResponse)(
    “您的请求出现问题”,
    ValidityResponseType.ERR,
    输入
    ));
    })
    )
    }
    createValidityResponse(消息:string,responseType:ValidityResponseType,响应:number):ValidityResponseModel{
    返回{
    消息
    响应类型,
    响应
    }作为ValidityResponseModel
    }
    }
    
    使用服务的组件 因为在最初的问题中,当用户点击enter时,您执行检查,所以我选择实现一个表单

    组件
    @组件({
    templateUrl:'./demo.component.html',
    样式URL:['./demo.component.scss']
    })
    导出类DemoComponent实现OnInit{
    组:FormGroup;
    responseType=ValidityResponseType;
    validityResponse!:ValidityResponseModel;
    构造函数(私有fb:FormBuilder,私有服务:ApiLookupService){
    this.group=fb.group({
    输入:fb.control(0,[Validators.minLength(1)])
    })
    }
    ngOnInit():void{
    }
    //提交。
    对于
    
      private baysUrl = 'api/bays';
    
      bays$ = this.http.get<Bay[]>(this.baysUrl)
        .pipe(
          tap(data => console.log('Bays: ', JSON.stringify(data))),
          catchError(this.handleError)
        );
    
      /*--------------------------------------------------------------*/
      // Grab A Single Bay
      private baySelectedSubject = new BehaviorSubject<number>(0);
      baySelectedAction$ = this.baySelectedSubject.asObservable();
    
      selectedBay$ = combineLatest([
        this.bays$,
        this.baySelectedAction$
      ])
        .pipe(
          map(([bays, selectedBayNumber]) =>
            bays.find(bay => bay.bayCode === selectedBayNumber)
          ),
        );
    
      selectedBayChanged(selectedBayNumber: number): void {
        this.baySelectedSubject.next(selectedBayNumber);
      }
    
    onSubmit() {
         this.bayDoesNotExistError = false;
          this.bayService.selectedBayChanged(this.bayForm.get('bayStart').value);
          this.navCtrl.navigateForward([`/results/`]);
          this.bayForm.reset();
        }