RxJS 6+:类型 'Observable' 必须拥有一个返回迭代器的 'Symbol.iterator' 方法。

3
尝试从可观察对象中获取一个筛选后的值数组时,出现了以下错误:

Type 'Observable' must have a 'Symbol.iterator' method that returns an iterator.

代码如下:
export class ItemsService {

  orderItems: OrderItem[] = [];
  orderItemsUrl = 'http://localhost:5000/order-items/';

  getOrderItemsFromHttp(selectedOrderNumber): Observable<OrderItem[]> {
    const tempArr = [];
      const orderItems = of (this.http.get<OrderItem[]>(`${this.orderItemsUrl}`)
      .subscribe(res => {
            this.orderItems = res;
      }) );

    for (const orderItem of orderItems) {                        <--- Error here
        if (orderItem.orderNumber === selectedOrderNumber) {
          tempArr.push(orderItem);
        }
    }
    return of(tempArr);
  }  
}

如果我修改以下内容

for (const orderItem of orderItems) {

to

for (const orderItem of [orderItems]) {

错误消失了,但属性orderNumber不再被识别,而且Intellisense提示:

类型“Subscription”上不存在属性“orderNumber”

那我该如何修复它呢?


1
这些都是非常混乱的 RxJS。你想要实现什么? - bryan60
请详细描述您想要实现的目标... - bryan60
2个回答

3

我觉得您正在寻找这个:

  getOrderItemsFromHttp(selectedOrderNumber): Observable<OrderItem[]> {
    return this.http.get<OrderItem[]>(`${this.orderItemsUrl}`).pipe(
      map(orderItems => orderItems.filter(oi => oi.orderNuber === selectedOrderNumber))
    );
  }  

为了使这个工作正常,您需要导入map操作符:
import { map } from 'rxjs/operators';

提供了一个很好的替代方案,我不得不在我的代码中替换一些变量,但最终它非常好地工作了,非常感谢Bryan。 - Sami-L
很好,我很高兴能够帮助到你。 - bryan60
一切看起来都很好。我会添加一些日志并确保您的后端实际返回您期望的内容。 - bryan60
不知道您做出了什么修改,所以很难给出原因。请确保您拥有完整的代码,包括返回语句。 - bryan60
它起作用了,所以我将问题标记为已回答,并删除了可能与其他人无关的评论,请您也做同样的事情,谢谢。 - Sami-L

0

我建议将连接和查找业务逻辑数据的方式分开,这样从http更改为SignalR等不会意味着更改您的业务逻辑。

创建另一个服务,其任务仅是使用http请求搜索元素,您的ItemsService将使用该服务来搜索数据。

您无需重新构建数组

@Injectable ({
   providedIn: 'root'
})
export class RestService {
config: Config; // Your URLs
   getItems () {
     return this.http.get <OrderItem []> (this.config.itemURL, {note: 'response'});
   }
}

@Injectable ()
export class ItemsService {

  orderItems: OrderItem [];

constructor (private restService: RestService) {
}

getItems () {
   return new Observable ((observer) => {
    restService.getItems (). subscribe ((items) => {
      observer.next (items);
    });
  });
}

}


1
将 REST 调用包装在另一个 Observable 中的目的是什么? - bryan60
可以从组件或任何地方异步地使用它。基本上是多层编程,如果在同一个组件中进行http请求,则忽略了30年的软件工程。 - Maikel Luis
你已经可以异步地在任何地方使用它,而不必将其包装在完全多余的可观察对象中。return restService.getItems() 在功能和架构上几乎是相同的,没有大量不必要的额外内容。虽然你想要分离关注点,但是通过创建一个rest服务和一个items服务,你并没有获得太多好处,items服务已经通过http隔离了获取items的责任。简单的传递只是为了层次和复杂性而存在的层次和复杂性。 - bryan60
我完全赞同你的观点,但这只是一个例子。想象一下更复杂的应用程序,涉及SOAP、REST、WebSocket等多种通信协议。多层编程有益健康。 - Maikel Luis
1
Angular中的HTTP服务已经提供了这个功能。我不认为将其包装成REST服务以提供对资源的语义访问会带来任何收益,而无论复杂性如何,单独的资源服务已经提供了这个功能。一个更复杂的应用程序也不能证明在可观察对象周围添加随机可观察对象包装器是有道理的。 - bryan60

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接