简体   繁体   English

Angular 如何避免错误破坏 valueChanges

[英]Angular how to avoid that errors break valueChanges

In my angular 6 application, I have a problem with some rxjs operators.在我的 angular 6 应用程序中,我遇到了一些 rxjs 操作符的问题。 I have a search field and I need to call my service (service do GET request) when the user is typing in the field, it is working if the service doesn't have any errors like 500.我有一个搜索字段,当用户在该字段中输入时,我需要调用我的服务(服务执行 GET 请求),如果该服务没有任何错误(如 500),它就可以工作。

But a request with 500 error break the chain in the value change, probably I don't return the correct value from the service...但是 500 错误的请求破坏了值更改的链,可能我没有从服务中返回正确的值...

this is the search field in the component:这是组件中的搜索字段:

this.manufacturer.valueChanges
  .pipe(
    filter((value: string) => (value ? value.length > 2 : false)),
    tap(() => (this.loadingAutocomplete = true)),
    debounceTime(500),
    switchMap(val => this.frameService.getItems(val, "manufacturerAutocomplete")),
    tap(() => (this.loadingAutocomplete = false)),
    catchError(err =>
      return of([]))
  )
  .subscribe(
    manufacturers => {
      this.matchingManufacturers.next(manufacturers);
    },
    err => {
      this.loadingAutocomplete = false;
      this.matchingManufacturers.next([]);
    }
  );

And this is the service:这是服务:

getItems(value: string, endPoint: string) {
  return this.http.get(
    this.endPointUrlService.cutLinks(this.endPointUrlService.map.get("frames")) + "/search/" + endPoint
  ).pipe(
    map((res: string[]) => {
      if (res) {
        return res;
      } else {
        return [];
      }
    })
  );
}

First time user types something it works, if I have an erros the valueChanges is not invoked again.第一次用户输入一些它有效的东西,如果我有一个错误,则不会再次调用 valueChanges。 I need to handle the errors in the component, not in the service.我需要处理组件中的错误,而不是服务中的错误。

The observable that results from your rxjs statement on the valueChanges property is completed , and that is why it doesnt react anymore.由您对 valueChanges 属性的 rxjs 语句产生的 observable 已完成,这就是它不再反应的原因。

Important: an observable that errors, will be completed, and there is nothing that you can do to alter that behavior.重要提示:一个可观察到的错误,将完成,并且您无法改变该行为。

What you need to do is prevent the error from your endpoint service from flowing down into the switchMap statement, and further into the chain.您需要做的是防止端点服务的错误向下流入 switchMap 语句,并进一步流入链中。 If it flows into the chain, that chain will be be completed.如果它流入链条,则该链条将完成。 To prevent the error from flowing down, you need to return empty() when your api call throws an error.为了防止错误向下流,您需要在 api 调用抛出错误时返回 empty()。

getItems(value: string, endPoint: string) {
    return this.http.get(this.endPointUrlService.cutLinks(this.endPointUrlService.map.get("frames")) + "/search/" + endPoint).pipe(
      map((res: string[]) => {
        if (res) {
          return res;
        } else {
          return [];
        }
      }),
      catchError(err => {
          // report error to user
          console.log(err);
          // Important: stop observable from emitting anything
          return empty();
      })
    );
}

More info on the subject:http://www.syntaxsuccess.com/viewarticle/error-handling-in-rxjs有关该主题的更多信息:http ://www.syntaxsuccess.com/viewarticle/error-handling-in-rxjs

Catch error earlier - in the service layer, like this:更早地捕获错误 - 在服务层中,如下所示:

 getItems(value: string, endPoint: string) {
        return this.http.get(this.endPointUrlService.cutLinks(this.endPointUrlService.map.get("frames")) + "/search/" + endPoint).pipe(
          map((res: string[]) => {
            if (res) {
              return res;
            } else {
              return [];
            }
          }),
          catchError(err => return of([]))
    );
  }

Probably this method solve my problem, this is the component, and the service doesn't catch anything:可能这个方法解决了我的问题,这是组件,服务没有捕获任何东西:

this.manufacturer.valueChanges
  .pipe(
    filter((value: string) => (value ? value.length > 0 : false)),
    tap(() => (this.loadingAutocomplete = true)),
    debounceTime(500),
    switchMap(val =>
      this.frameService.getItems(val, "manufacturerAutocomplete").pipe(
        catchError(err => {
          handleError(err);
          this.loadingAutocomplete = false;
          return [];
        })
      )
    ),
    tap(() => (this.loadingAutocomplete = false))
  )
  .subscribe(
    manufacturers => {
      this.matchingManufacturers.next(manufacturers);
    },
    err => {
      this.loadingAutocomplete = false;
      this.matchingManufacturers.next([]);
    }
  );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM