typescript 向API发出一个请求,处理结果并发出另一个API请求

kyxcudwk  于 2023-05-01  发布在  TypeScript
关注(0)|答案(2)|浏览(184)

我第一次来这里不是为了阅读,而是为了问一个问题,因为我已经在RxJS上失去理智两天了。
我需要触发两个API调用:第一个得到pricelists的列表。响应是一个以ID作为键的对象。我在这里留下一个片段:

{
    "a64cb186455a5a0b5ea1f12e027ce384": {
        "supplier_name": "Supplier_1",
        "pricelists": [
            {
                "status": "enabled",
                "title": "Pricelist_1",
                "pricelist_id": "839b47d67954a9dec375a40652f93b52",
            },
            {
                "status": "expired",
                "title": "Pricelist_2",
                "pricelist_id": "1aed04c948bc63e3b6f8100b0e410afd",

            }
        ]
    }
}

在这个对象中,我只需要pricelists数组。之后,我还需要过滤价格列表,以便只保留启用的价格列表。然后,从结果数组中,我检查是否有剩余的价格列表。如果至少有一个pricelist,我将所有pricelist保存在一个数组中,并将数组的第一个pricelist作为选定的pricelist。
话虽如此,现在我有一个精选的价目表。从这里开始,我需要获取所选pricelist的pricelist_id,并将其用于另一个API调用。第二个API调用将加载这个价目表中的葡萄酒。
我在这里也留下了一个回应的片段:

[
   {
       "producer": "Producer_1",
       "id_prod": "90e2ac8275a68d9eb3a246735e7546cd",
       "wines": [
           {...},
           {...},
           {...},
           {...}
       ]
   },
   {
       "producer": "Producer_2",
       "id_prod": "54e2bf8275a68d9eb3a246735e7546zq",
       "wines": [
           {...},
           {...},
           {...},
           {...}
       ]
   }
]

在这个对象数组中,我只需要“wines”键中的所有对象。所以我需要把所有的对象放在一个数组中,这样我就可以在HTML端对这个数组进行for循环。
此外,还有一个用于更改所选价目表的模式。使用以前保存的价目表,我可以更改所选的价目表。当我改变活动的价格表时,我需要再次调用API来加载葡萄酒。
我已经实现了所有这些代码,但它是另一个订阅中的订阅,我真的不喜欢它。这感觉很笨拙,这不是处理这件事的最佳方式。我留下片段,这样它更容易理解:

loadPricelists() {
    this.pricelistsService.getConnectionPricelists().subscribe(data => {
      for(let supplier in data) {
        data[supplier]["pricelists"].forEach(pricelist => {
          pricelist["supplier_name"] = data[supplier]["supplier_name"];
          this.pricelists.push(pricelist);
        });
      };  
      this.pricelists = this.pricelists.filter(pricelist => pricelist.status != 'expired');
      if(this.pricelists.length > 0) {
        this.selectedPricelist = this.pricelists[0];
        this.loadPricelistWines(this.selectedPricelist.pricelist_id);
      }
    });
  }

  loadPricelistWines(pricelist_id) {
    this.wines = [];
    this.pricelistsService.getPricelistWines(pricelist_id, this.available_prods).subscribe(data => {
      for(let i in data) {
        this.wines.push(...data[i].wines);
      }
      this.totalWines = this.wines;
      this.selectedPricelist = this.pricelists.filter(prcl => prcl.pricelist_id == pricelist_id)[0];
      this.changeDetection.detectChanges();
    });
  }

所以,在语法上,我需要把上面的代码转换成RxJS风格。请帮帮我,我真的疯了!!任何提示将不胜感激!
我尝试实现RxJS,我设法在活动价格列表中获取价格列表和葡萄酒,但是当我更改活动价格列表时,什么也没有发生,HTML也没有更新。我也不太清楚我在用RxJS做什么

djmepvbi

djmepvbi1#

开始了,无聊了。一个问题太多了
这是我到达的地方的Stackblitz
建议添加类型

type PriceListStatus = 'enabled' | 'expired';
type PriceList = {
  status: PriceListStatus;
  title: string;
  pricelist_id: string;
};
type SupplierData = {
  supplier_name: string;
  pricelists: Array<PriceList>;
};
type PriceListData = Record<string, SupplierData>;
type WineData = {
  producer: string;
  id_prod: string;
  wines: any[]; // but type this too!
};

RxJ的关键是管道,并且只在“sink”上订阅,因此从源到sink有一个完整的链。

const dataToPriceListIds$ = of(PRICE_LIST_DATA).pipe(
  // From this object, I only need the array of pricelists
  // After that, I also need to filter the pricelists in order to keep only the enabled ones
  map((data) => mapToPriceIds(data, 'enabled')),
  debugPipe('Filtered price ids'),
  // Then, from the resulting array, I'm checking if there is any pricelist left.
  filter(isArrayLengthGreaterThanZero),
  debugPipe('Only emit if array greater than zero')
);

const selectedPriceListId$ = dataToPriceListIds$.pipe(
  // first pricelist of the array the selected pricelist
  map((arr) => arr[0]),
  debugPipe('First item of the array')
);

const wineData$ = selectedPriceListId$.pipe(
  // mock api call using id
  switchMap((id) => of(WINE_DATA).pipe(delay(300))),
  debugPipe('Wine data')
);

wineData$.subscribe();
xiozqbni

xiozqbni2#

你有没有尝试使用RXJS的MergeMap
mergeMap允许您从第一个API调用中获取结果,并在它之后立即设置第二个API调用
差不多是这样

this.service1.Req1()
        .pipe(
            take(1),
            mergeMap(response1 => 
                this.service1.Req2(response1).pipe(
                    take(1),
                    map(response2 => {
                        console.log(response1);
                        console.log(response2);
                    })
                )
            )
        )

我不是很确定我理解你的问题,对我来说你想做的是一个经典的API调用后,根据结果的第二个api调用

相关问题