从角度服务获取最终数据

时间:2018-12-19 09:43:45

标签: javascript angular typescript angular6 angular-services

在我的angular 6应用程序中,我有一个product_id,它是一个数组,

product_id: any = ["123", "456"];

ngOnInit:

  ngOnInit() {
    this.product_id.forEach(element => {
      this.httpClient.get('https://api.myjson.com/bins/hiolc').subscribe(res => {
        this.productList = [];
        res.products.forEach( item => {
          this.productList.push(item);
        });
      })
    })
    console.log(this.productList);
  }

console.log(this.productList);中,我需要将预期结果设置为

   [{
      "product_name": "Product One",
      "product_information": {
        "template_details": [
          {
            "template_name": "RACE Template",
            "productProperties": [
              {
                "property_id": 2518427931,
                "property_name": "Length",
                "property_value": "12 cm"
              },
              {
                "property_id": 2621195440,
                "property_name": "Width",
                "property_value": "10 cm"
              },
              {
                "property_id": 2621195441,
                "property_name": "Height",
                "property_value": "20 cm"
              }
            ]
          }
        ]
      }
    },
    {
      "product_name": "Product Two",
      "product_information": {
        "template_details": [
          {
            "template_name": "RACE Template",
            "productProperties": [
              {
                "property_id": 2518427931,
                "property_name": "Length",
                "property_value": "15 cm"
              },
              {
                "property_id": 2621195440,
                "property_name": "Width",
                "property_value": "12 cm"
              },
              {
                "property_id": 2621195441,
                "property_name": "Size",
                "property_value": "Medium"
              }
            ]
          }
        ]
      }
    }]

但是会给出空数组[] ..

如何等待服务完成,然后将数据存储到productList

我需要forEach this.product_id.forEach(element,因为在基于foreach的真实应用程序中,我将获得通过url发送的每个产品ID的产品列表。

在发送完所有产品ID之后,请根据forEach完成整个服务后帮我存储数据,然后获取最终产品列表。

有效的堆叠闪电战: https://stackblitz.com/edit/flatternstructure-dvzpjv

我再次明确,在我的真实应用程序中,我需要传递ID才能像product value一样获得https://api.myjson.com/bins/hiolc + element。.

如果我得到最终的productList,那么我需要对最终的productList做另一项功能,所以只有我期望最后在productList中完成的数据,而不是{{1 }} ..

7 个答案:

答案 0 :(得分:1)

使用rxjs.concat:

[编辑]

stackblitz上可用

...
import { concat } from 'rxjs';
import { map } from 'rxjs/operators';
...

ngOnInit() {
  this.productList = [];
  concat(
    this.product_id.map(
      element => this.httpClient.get('https://api.myjson.com/bins/hiolc')
    )
  ).pipe(
    map((res: any) => this.productList = this.productList.concat(res.products))
  ).subscribe(res => {
    console.log(res);
    console.log(this.productList);
  });
}

希望有帮助。

答案 1 :(得分:0)

更新

这将起作用:

import { zip } from 'rxjs'
....
ngOnInit() {
  const obs = []
  this.product_id.forEach(element => {
    obs.push(this.httpClient.get('https://api.myjson.com/bins/hiolc'))
  })
  zip(...obs).subscribe(res => {
    res.forEach(r => this.productList.push(...r.products))
    console.log(this.productList)
  })
}

stackblitz: https://stackblitz.com/edit/flatternstructure-nk9yha

答案 2 :(得分:0)

您有两个问题:您记录得太早了,并且覆盖了阵列。

首先,登录很快。您触发请求(ids.forEach(id => this.http....))。然后在那之后,您执行console.log-但结果尚未返回。甚至还没有触发请求。这就是为什么您看到空数组的原因。将console.log语句移到this.productList.push(...)语句下,您会看到它。

第二个问题是,您触发并行请求,并且它们都使用以下行重置产品列表this.productList = [];。

您只想这样做一次。

所有这些的更好的版本是:

ngOnInit() {
  forkJoin(product_ids) // fire them in parallel.
    .pipe(
       map(id => this.http.get('https://api.myjson.com/bins/hiolc' + id)),   // fetch the things
       map(items=> this.productList = this.productList.concat(items)),
    )
    .subscribe(() => console.log('Done, items:', this.productList));

更好的版本是:

 ngOnInit() {
    this.someService.getProductItems(productIds)
        .subscribe(productList => this.productList = productList);
}

意思是,将Http调用移到服务中,在其中执行所有这些操作,并使组件更清洁,更简单。

答案 3 :(得分:0)

为什么不按角度文档中的描述创建真实的服务?

在这里您要在组件内实现httpClient透明性 https://angular.io/tutorial/toh-pt4#subscribe-in-heroescomponent

我建议您首先创建一个可注入服务,该服务将在像HTTPClient这样的组件构造函数中使用

然后,我将在服务中获取数据并订阅它。

答案 4 :(得分:0)

您能尝试一下吗?

ngOnInit() {
    let counter = 0;
    this.productList = [];
    this.product_id.forEach(element => {
      this.httpClient.get('https://api.myjson.com/bins/hiolc').subscribe(res => {
        res.products.forEach( item => {
          this.productList.push(item);
        });
        counter = counter + 1;
        if(counter === this.product_id.length){
            console.log(this.productList);  
            // call your next operation here
        }
      })
    })
}

答案 5 :(得分:0)

这个怎么样? StackBlitz

import { forkJoin } from 'rxjs';

....

ngOnInit() {
    forkJoin(
      this.product_id.map(element => this.httpClient.get('https://api.myjson.com/bins/hiolc'))
    )
    .subscribe((res) => {
        this.productList = this.productList.concat(res);
        console.log(this.productList);
    });
}

答案 6 :(得分:0)

这也可以:

this.productList$ = from(this.product_id).pipe(
    mergeMap(() =>  this.httpClient.get('https://api.myjson.com/bins/hiolc')),
    scan((productList, item) => [...productList, item], [])
    tap((productList) => console.log(productList))
).subscribe(() => {}) // or async pipe in a template