如何在一个redux-saga中从不同的API获取数据?

问题描述

我有一个使用redux-saga的React项目,我需要调用2个API来获取所需的所有数据。

如果我需要提取所有产品,通常会这样做:

function* fetchProducts() {
  const products = yield call(API.getProducts)
  yield put({type: "UPDATE_PRODUCTS",products})
}

现在想象一下我的product对象有一个brandId字段,我可以使用该字段从另一个API提取 brand 数据。

我想:

  1. 获取所有产品
  2. 提供产品信息,并为每个产品加载其品牌信息
  3. 更新我的products对象以包括品牌信息
  4. 以我的全局状态保存新的products对象

我尝试过这样的事情:

function* fetchProducts() {
  const products = yield call(API.getProducts)
  const productsWithBrand = products.map((product) => {
    const brand = yield call(API.getBrand,product.brandId)
    return {
      ...product,brandData: brand,}
  })
  yield put({type: "UPDATE_PRODUCTS",productsWithBrand})
}

哪个给我错误

解析错误:意外的保留字'yield'

在阅读this thread之后,我理解了为什么会发生错误,但是我无法弄清楚实现所需内容的正确语法。

是否有实现我需要的通用模式?

解决方法

从语法上讲,在传递给map的函数中 yield 无效,因为map对生成器一无所知。常见的模式是选择for...of循环或常规for循环对集合中的每个项目执行异步操作。 https://medium.com/free-code-camp/redux-saga-common-patterns-48437892e11c

function* fetchProducts() {
    const products = yield call(API.getProducts);
    const productsWithBrands = [];
    for (let product of products) {
        const productWithBrand = yield call(API.getBrand,product.brandId);
    
        const { error } = yield race({
            success: take(SUCCESS),error: take(FAILURE),});
        
        if(error) {
            // Implement specific error handling
            // eg: break;
        }
        productsWithBrands.push(productWithBrand);          
    }
   yield put({type: "UPDATE_PRODUCTS",productsWithBrands });
}