角度打字稿中的查找/过滤器功能引发错误

时间:2020-07-17 00:03:39

标签: angular typescript rxjs

我正在尝试使用角度打字稿通过ID查找记录,这是我在下面给出的数组

     {
  "products": [
    {
      "id": "1731002618",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "rating": 3,
      "price1": 34.00,
      "cuom1": "case",
      "price2": 1.97,
      "cuom2": "sq. ft.",
      "saving": 22,
      "was": 41.48,
      "addToCart": "addToCart",
      "badges": [
        "badge-ECO",
        "badge-NLP",
        "badge-SB",
        "badge-ES"
      ]
    },
    {
      "id": "1911002437",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "price1": 34.00,
      "cuom1": "case",
      "promo": "+25% Off Select Products",
      "addToCart": "viewDetails"
    },
    {
      "id": "1661232636",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "price1": 41.48,
      "cuom1": "case",
      "price2": 2.40,
      "cuom2": "sq. ft.",
      "addToCart": "viewDetails"
    },
    {
      "id": "1231002635",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "rating": 4,
      "price1": 41.48,
      "cuom1": "case",
      "addToCart": "viewDetails"
    },
    {
      "id": "1561002634",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "rating": 4,
      "addToCart": "viewDetails"
    },
    {
      "id": "1781002633",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "price1": 41.48,
      "cuom1": "case",
      "addToCart": "viewDetails"
    },
    {
      "id": "1121002632",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "price1": 41.48,
      "cuom1": "case",
      "addToCart": "addToCart"
    },
    {
      "id": "1461002631",
      "imageUrl": "product_1.jpg",
      "brand": "Max Home Collection",
      "title": "5.2 cu. ft. High-Efficiency Stackable Front-Load Washer in White",
      "model": "7L12X165/8045CL",
      "price1": 41.48,
      "cuom1": "case",
      "addToCart": "viewDetails"
    }
  ]
}

我正在做这样的事情

getProductByID(postid:string):Product {
    this.http.get<Product[]>(this.configUrl).subscribe(data => {
             this.product=data;    
    });
    
    // return this.http.get<Product[]>(this.configUrl);
    return { ...this.product.find(p=>p.id===postid) };
}
ngOnInit() { 
this.route.paramMap.subscribe((paramMap)=>{ 
    if(paramMap.has("postid")) { 
        alert('differentiate '+paramMap.get("postid"));
        alert('before call');
        var p = this.Service.getProductByID(paramMap.get("postid"))
                           .subscribe(data=>{ console.log(data);});
    }) 

} 

它说find函数出错,我也尝试了filter函数,但是仍然一样, 非常感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

可观察变量可以使用toPromise()转换为Promise:

组件


ngOnInit() { 
this.route.paramMap.subscribe((paramMap)=>{ 
    if(paramMap.has("postid")) { 
        alert('differentiate '+paramMap.get("postid"));
        alert('before call');
        const product = await this.Service.getProductByID(paramMap.get("postid"));
        console.log('product is',product);
    }) 

} 

服务

async getProductByID(postid:string):Promise<Product>
   {
        const products = await this.http.get<Product[]>(this.configUrl).toPromise();

        return products.find(product=>product.id===postid);
   }

答案 1 :(得分:1)

您正在尝试在this.product上运行find。可观察变量是异步的,因此您的返回将在this.product=data运行之前发生。

您将需要将其作为可观察者返回,并在其他地方订阅

getProductByID(postid:string):Observable<Product> { // Not actually sure if this is returning a product or not, its an Observable of something...
   this.http.get<Product[]>(this.configUrl)pipe(map(data => {
       this.product=data; 
       return { ...this.product.find(p=>p.id===postid) };
   })
  );
   
}

// Then when you need to call this method...
this.getProductByID('someId').subscribe(data => {
   // this will be `{ ...this.product.find(p=>p.id===postid) };` 
  console.log(data);
})

答案 2 :(得分:1)

不订阅您的服务!

您的getProductsByID()方法应定义http调用和返回所需形状所需的数据转换。您应该返回一个可观察的对象,并让服务的使用者订阅它。

通过.pipe()方法,您可以使用各种运算符来转换流中的值。在这种情况下,您可以使用map()运算符将传入的产品数组映射到单个产品(如果该产品不存在,则为未定义)。

服务:

// Returns an observable stream that emits a single
// product (after receiving the entire product
// list and filtering down to one by postid)

getProductByID(postid:string):Observable<Product|undefined> {
    return this.http.get<Product[]>(this.configUrl).pipe(
        map(products => products.find(p => p.id === postid))
    );
}

根据您需要在组件中执行的操作,如果您利用模板中的async pipe,甚至可能不需要在其中进行订阅。让我们定义几个不同的Observable $,以便更轻松地了解正在发生的事情。

我们可以使用ActivatedRoute来获取参数作为可观察的源。

组件:

postid$: Observable<string>;
product$: Observable<Product>;

constructor(private route:ActivatedRoute) { }

ngOnInit() {
    // Stream that emits the latest value of postid.
    // Doesn't emit if the value is null/undefined.

    postid$ = route.params.pipe(
        map(p => p.postid),
        filter(p => !!p)
    );


    // Stream that emits the latest value of product. Takes 
    // value of postid$ and uses it to make http call.

    product$ = postid$.pipe(
        switchMap(postid => this.Service.getProductByID(postid)),
        tap(product => console.log('product:', product))
    ); 
} 

您可以使用tap运算符执行副作用类型的操作,也可以仅登录控制台。

在您的模板中:

<div *ngIf="product$ | async as product">
   <h1>{{ product.title }}</h1>
   <p>Model:{{ product.model }}</p>
   <p>Price:{{ product.price }}</p>
   <img src="{{ product.imageUrl }}">
</div>

异步管道非常好,因为它将自动为您订阅/取消订阅。