You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Redux-Saga中调用另一个Generator函数?

在getMyCollectionDetails中为每个模板获取对应硬币详情

需求说明

我需要在getMyCollectionDetails生成器函数内,通过getTemplateCoins生成器获取active和unactive列表中每个模板ID对应的硬币详情,最终返回包含这些额外信息的新列表,再传递给getMyCollectionDetailsSuccess action。

现有代码

MyCollectionSaga

export function* getMyCollectionDetails(api) {
  try {
   const responseDetails = yield makeRequest(api, api.getMySocialProfile, null);
   const responseBadges = yield makeRequest(api, api.getBadges, null);
   const responseTemplates = yield makeRequest(api, api.getTemplates, null);

  if (responseDetails.ok && responseBadges.ok && responseTemplates.ok) {
    const templates = responseTemplates.data.results.map((e) => parseTemplate(e));
    const active = templates.filter((e) => e.active);
    const unactive = templates.filter((e) => !e.active);
 
    // 希望在这里调用getTemplateCoins,传入active和unactive列表中每个项的id
    // 把结果存入新数组,再传给下方的getMyCollectionDetailsSuccess
    yield put(
      MyCollectionsActions.getMyCollectionDetailsSuccess(
       responseDetails.data.result,
       responseBadges.data.result,
       active,
       unactive
     )
    );
   }
 } catch (error) {
   log(error);
 }
}

export function* getTemplateCoins(api, { templateId }) {
  try {
    const params = { templateId };
    const response = yield makeRequest(api, api.getTemplateCoins, params);

    if (response.ok) {
      const coinsCollections = response.data.results.coins.filter((e) => e.inCollection);
      const coinsMissing = response.data.results.coins.filter((e) => !e.inCollection);

      const coins = [
        { title: i18n.t('common:collectionTemplateSectionCollected'), data: coinsCollections },
        { title: i18n.t('common:collectionTemplateSectionMissing'), data: coinsMissing },
      ];

      yield put(CollectionTemplateActions.getTemplateCoinsSuccess(coins));
    } else {
      yield put(
        CollectionTemplateActions.getTemplateCoinsFailure(i18n.t('common:genericErrorMessage'))
      );
    }
  } catch (error) {
    log(error);
    yield put(
      CollectionTemplateActions.getTemplateCoinsFailure(i18n.t('common:genericErrorMessage'))
   );
 }
}

MyCollectionRedux

const getMyCollectionDetails = (state) => {
 return { ...state, isLoading: true, error: false, message: '' };
};

const getMyCollectionDetailsSuccess = (
  state,
  { socialProfile, allBadges, templatesActivated, templatesUnactivated }
) => {
  
 return {
   ...state,
   socialProfile,
   allBadges,
   templatesActivated,
   templatesUnactivated,
   isLoading: false,
   error: false,
  };
};

const getMyCollectionDetailsFailure = (state, { message }) => {
  return { ...state, message, isLoading: false, error: true };
};

解决方案

核心思路

  1. 重构getTemplateCoins:让它直接返回硬币数据,而非单独派发action,这样可以在getMyCollectionDetails中直接获取结果。
  2. 批量获取详情:使用Saga的all和call方法,并行遍历active和unactive列表,为每个模板调用getTemplateCoins并合并结果。
  3. 传递新列表:将包含硬币详情的模板列表传递给成功action,Reducer无需额外修改(只需确保模板对象新增的coins属性能被正常存储)。

修改后的代码

重构后的getTemplateCoins

export function* getTemplateCoins(api, templateId) {
  try {
    const params = { templateId };
    const response = yield makeRequest(api, api.getTemplateCoins, params);

    if (response.ok) {
      const coinsCollections = response.data.results.coins.filter((e) => e.inCollection);
      const coinsMissing = response.data.results.coins.filter((e) => !e.inCollection);

      // 返回硬币数据,而非直接派发action
      return [
        { title: i18n.t('common:collectionTemplateSectionCollected'), data: coinsCollections },
        { title: i18n.t('common:collectionTemplateSectionMissing'), data: coinsMissing },
      ];
    } else {
      throw new Error(i18n.t('common:genericErrorMessage'));
    }
  } catch (error) {
    log(error);
    throw error; // 抛出错误让上层处理
  }
}

修改后的getMyCollectionDetails

export function* getMyCollectionDetails(api) {
  try {
    const responseDetails = yield makeRequest(api, api.getMySocialProfile, null);
    const responseBadges = yield makeRequest(api, api.getBadges, null);
    const responseTemplates = yield makeRequest(api, api.getTemplates, null);

    if (responseDetails.ok && responseBadges.ok && responseTemplates.ok) {
      const templates = responseTemplates.data.results.map((e) => parseTemplate(e));
      const active = templates.filter((e) => e.active);
      const unactive = templates.filter((e) => !e.active);

      // 并行获取所有active模板的硬币详情,合并到模板对象中
      const activeWithCoins = yield all(
        active.map((template) =>
          call(getTemplateCoins, api, template.id).then((coins) => ({ ...template, coins }))
        )
      );

      // 并行获取所有unactive模板的硬币详情,合并到模板对象中
      const unactiveWithCoins = yield all(
        unactive.map((template) =>
          call(getTemplateCoins, api, template.id).then((coins) => ({ ...template, coins }))
        )
      );

      yield put(
        MyCollectionsActions.getMyCollectionDetailsSuccess(
          responseDetails.data.result,
          responseBadges.data.result,
          activeWithCoins,
          unactiveWithCoins
        )
      );
    }
  } catch (error) {
    log(error);
    // 可选:派发全局失败action
    yield put(MyCollectionsActions.getMyCollectionDetailsFailure(i18n.t('common:genericErrorMessage')));
  }
}

注意事项

  • 如果getTemplateCoins原本需要单独触发(比如其他场景调用),可以保留原函数,新增一个纯获取数据的版本(比如fetchTemplateCoins)来避免冲突。
  • 并行请求使用all可以提升性能,避免串行请求的等待时间。
  • 错误处理可以根据需求调整,比如部分请求失败时是否继续处理其他成功的结果。

内容的提问来源于stack exchange,提问作者mistybui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:10:34