fromEvent运算符在“未找到项目搜索结果”后未触发

时间:2019-07-07 04:30:32

标签: javascript angular typescript rxjs observable

  1. 我搜索一个物品
  2. 如果找不到该项目(404),我会得到一个预期的错误
  3. 同样,如果我尝试搜索新商品, fromEvent根本不会触发

不确定为什么吗?

fromEvent(this.searchInput.nativeElement, 'keyup').pipe(
    tap(() => console.log('qorking')),
    map((event: any) => {
      if (event.keyCode === 17 || event.keyCode === 91 || event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40 || event.keyCode === 13 || event.keyCode === 27) {
        return;
      }
      return event.target.value;
    }),
    filter((query: any) => {
      if (!this.loading && (!query || query == '')) {
        this.searchedResult = [];
        return false;
      }
      return true;
    })
    , debounceTime(275)
    , distinctUntilChanged() // If previous query is different from current
    , switchMap(query => {
      if (query && query !== '') {
        query = query.trim();
        this.loading = true;
        return this.cartService.searchItemByName(encodeURIComponent(query), this.shopID.shop_id.toString());
      } else {
        this.searchedResult = [];
        this.loading = false;
        return EMPTY;
      }
    }),
    // subscription for response
).subscribe((res: any) => {
  this.searchedResult = [];
  let data = res.result;
  console.log('res', data);
  this.searchedResult = data;
  this.loading = false;
  if (data.length) this.setSelectedItem(data[0], 0);
}, (err) => {
  console.log('error', err);
  this.loading = false;
  this.searchedResult = [];
  this.toaster.error(err.error.message || "Something went wrong!");
})

2 个答案:

答案 0 :(得分:0)

我看到您正在传递给该可观察对象的运算符的函数中的this上调用方法,这意味着在该可观察对象发出事件时会触发副作用。

关于此代码如何更改世界状态,我没有完整的上下文,但是一种可能是,您订阅keyup事件的元素不再在初始页面之后显示在页面上出现404。

这很可能不会触发任何错误,因为可观察对象只是订阅了错误的元素。但是我需要更多地了解周围的环境,才能自信地说出来。

答案 1 :(得分:0)

正如您提到的那样,在404情况下,您的错误回调被调用,因此您的代码按可观察的设计预期进行。根据可观察的设计,如果在可观察的管道中发生错误(异常),则可观察的处于错误状态,并且无法发出新值(https://blog.angular-university.io/rxjs-error-handling/),并且可以视为已完成[即,无法发出新值]。因此,一旦发生错误,keyup事件就不会触发。

现在要在发生错误的情况下保持源可观察的活动状态(在您的情况下,keyup事件在发生错误的情况下会引发错误),请使用catchError运算符处理可观察的错误并抛出错误。在您的情况下,this.cartService.searchItemByNam方法返回一个可观察值。因此,让我们这样更改代码:

fromEvent(this.searchInput.nativeElement, 'keyup').pipe(
    tap(() => console.log('qorking')),
    map((event: any) => {
      if (event.keyCode === 17 || event.keyCode === 91 || event.keyCode === 37 || event.keyCode === 38 || event.keyCode === 39 || event.keyCode === 40 || event.keyCode === 13 || event.keyCode === 27) {
        return;
      }
      return event.target.value;
    }),
    filter((query: any) => {
      if (!this.loading && (!query || query == '')) {
        this.searchedResult = [];
        return false;
      }
      return true;
    })
    , debounceTime(275)
    , distinctUntilChanged() // If previous query is different from current
    , switchMap(query => {
      if (query && query !== '') {
        query = query.trim();
        this.loading = true;
        return this.cartService.searchItemByName(encodeURIComponent(query), this.shopID.shop_id.toString())
.pipe(
  catchError(err => {
    console.log('error', err);
          this.toaster.error(err.error.message || "Something went wrong!");
          //in case of error let’s emit an empty array like you doing in other else conditions
          return of([]):
  })
);
      } else {
        this.searchedResult = [];
        this.loading = false;
        return EMPTY;
      }
    }),
    // subscription for response
).subscribe((res: any) => {
  this.searchedResult = [];
  let data = res.result;
  console.log('res', data);
  this.searchedResult = data;
  this.loading = false;
  if (data.length) this.setSelectedItem(data[0], 0);
}, (err) => {
  console.log('error', err);
  this.loading = false;
  this.searchedResult = [];
  this.toaster.error(err.error.message || "Something went wrong!");
})

希望有帮助。

顺便说一句,您的代码有很多改进的地方。