在 Angular 5 中使用 SwitchMap 订阅

Posted

技术标签:

【中文标题】在 Angular 5 中使用 SwitchMap 订阅【英文标题】:Subscribing with SwitchMap in Angular 5 【发布时间】:2019-03-25 05:34:57 【问题描述】:

我正在尝试显示包含所有产品的页面和包含类别的部分,但只有类别正在呈现。

我没有在页面上看到产品。

控制台显示错误:

main.653279d3d097093b55e7.js:1 ERROR Error: InvalidPipeArgument: '[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object],[object Object]' for pipe 't'

我的代码:

import  Component, OnInit  from '@angular/core';
import  ProductService  from '../product.service';
import  Observable, Subscription  from 'rxjs';
import  AngularFireList  from 'angularfire2/database';
import  map, switchMap, filter  from 'rxjs/operators';
import  CategoryService  from '../category.service';
import  ActivatedRoute  from '@angular/router';
import  Product  from '../models/product';

@Component(
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css']
)
export class ProductsComponent implements OnInit 
  products: any = ;
  productsRef: AngularFireList<any>;
  filteredProducts;
  categories: Observable<any>;
  categoriesRef: AngularFireList<any>;
  category;

  constructor(route: ActivatedRoute, private productService: ProductService, private categoryService: CategoryService) 

    this.productsRef = productService.getAll();

    this.products = this.productsRef.snapshotChanges().pipe(
      map(changes =>
        changes.map(c => (key: c.payload.key, ...c.payload.val() ))
      )).switchMap (products => 
        this.products = products;
        return route.queryParamMap;
      ).subscribe (params => 
        this.category = params.get('category');
        this.filteredProducts = (this.category) ?
          this.products.filter(p => p.category === this.category) : this.products;
      );

    this.categoriesRef = this.categoryService.getAll();

    this.categories = this.categoriesRef.snapshotChanges().pipe(
        map(changes =>
          changes.map(c => (key: c.payload.key, ...c.payload.val() ))
        )
      );

有解决此问题的建议吗?

【问题讨论】:

向我们展示您用于显示数据的pipe 的代码 getAll() return this.db.list('/products'); 【参考方案1】:

你应该使用pipe()

 this.products = this.productsRef.snapshotChanges().pipe(
      map(changes =>
        changes.map(c => (key: c.payload.key, ...c.payload.val() ))
      ),
switchMap (products => 
        this.products = products;
        return route.queryParamMap;
      )
).subscribe (params => 
        this.category = params.get('category');
        this.filteredProducts = (this.category) ?
          this.products.filter(p => p.category === this.category) : this.products;
      );

【讨论】:

您的回答很好,但我们可以看到作者已经使用pipe(...),但并非在所有情况下都使用。由于switchMap 超出pipe 方法范围并且它以旧方式使用(按点链接函数运算符)我要补充一点,所有这些都应该在pipe(...) 内。 Buczkowski,我该怎么做?【参考方案2】:

switchMap签名期望这个函数应该返回Observable&lt;any&gt;:

public switchMap(project: function(value: T, ?index: number): ObservableInput, resultSelector: function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any): Observable

当您返回 route.queryParamMap 时,它不是 ObservableInput 类型。尝试替换这一行:

return route.queryParamMap;

用这个:

return Observable.from(route.queryParamMap);

编辑

由于我的错误,我的第一个答案无效,我尝试将您的 strem 重写为不使用 pipe 并在其开头使用 switchMap 的字符串,以防止重新查询不完整流。

this.products = this.productsRef.snapshotChanges()
.switchMap((products: AngularFireAction<DatabaseSnapshot>[]) => 
    return Observable.of(products); // Just re-emit things to guard re-query interruption
)
.map((snap: AngularFireAction<DatabaseSnapshot>[]) =>  /* Do data manipulation */
  let mappedProducts = snap.map((s: AngularFireAction<DatabaseSnapshot>) => 
    return key: s.payload.key, ...c.payload.val() 
  )
  return mappedProducts;
)
.do((mappedProducts: any) =>  /* Side effects */
  this.products = mappedProducts;
)
.concatMap(mappedProducts => 
  return route.queryParamMap;
)
.subscribe (params => 
  this.category = params.get('category');
  this.filteredProducts = (this.category) ?
    this.products.filter(p => p.category === this.category) : this.products;
);

【讨论】:

错误“类型 上不存在属性'get'。与 .this.category = params.get('category') 一致。单词“get”带下划线 @Vini Pineda 非常抱歉,根据角度文档 queryParamMap alredy 是以下类型的可观察对象:Observable&lt;ParamMap&gt;。当您应用 mi“修复”时,您的代码将与嵌套的 observables (Observable&lt;Observable&lt;ParamMap&gt;&gt;) 一起使用,这是您完全不会使用的。很抱歉我的错误,我没有检查文档。

以上是关于在 Angular 5 中使用 SwitchMap 订阅的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2:为啥在检索路由参数时使用 switchMap?

为啥 switchMap 在 Angular 拦截器(Angular 9)中不起作用

在Angular App中的Obseable POST请求中使用switchMap

使用 switchmap 和 forkjoin 链接 observables 不能按预期工作 angular typescript rxjs

来自 Angular Redux Store 的 SwitchMap 结果

使用SwitchMap()处理取消先前的请求