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

在单个@ngrx/effect中按顺序执行多个Http请求的实现咨询

@ngrx Effect 串行请求实现方案

你当前的concatMap用法存在错误,concatMap要求传入的是一个返回Observable的回调函数,而非直接传入Observable数组。要实现四个请求按串行顺序执行、前一个请求完成后才触发下一个,可按以下方式修改:

processOrder$ = createEffect(() => 
  this.actions$.pipe(
    ofType(OrderActions.PROCESS_ORDER),
    // concatMap接收触发action,返回串行执行的Observable流
    concatMap((action) => 
      // concat按传入顺序依次订阅内部Observable,前一个complete后才订阅下一个
      concat(
        this.service.addCrust(),
        this.service.addTopings(),
        this.service.sendToCook(),
        this.service.checkOut()
      ).pipe(
        // 只保留最后一个checkOut接口的返回值,需全量结果可替换为toArray()
        last(),
        map((checkOutResult) => OrderActions.processOrderSuccess({ data: checkOutResult })),
        // 任意步骤出错直接终止后续请求,触发失败Action
        catchError((error) => of(OrderActions.processOrderFailure({ error: error.message })))
      )
    )
  )
);

核心逻辑说明

  • 执行规则:concat会严格按照传入顺序执行请求,任意一个请求未完成前,后续请求不会发起,完全匹配按顺序处理的需求。
  • 结果处理规则:
    • 需获取所有请求的返回值时,将last()替换为toArray(),会将四个请求的返回值按执行顺序组装为数组传入后续map
    • 仅需最后一步checkOut的返回结果时,保留last()即可
    • 任意一步请求抛出错误都会直接进入catchError,可在失败Action中处理错误提示、状态回滚等逻辑

特殊场景适配

如果前一个请求的返回值需要作为后一个请求的入参,不能直接用concat,要改用concatMap链式调用,示例如下:

concatMap((action) => 
  this.service.addCrust().pipe(
    concatMap((crustRes) => this.service.addTopings(crustRes.id)),
    concatMap((topingsRes) => this.service.sendToCook(topingRes.list)),
    concatMap((cookRes) => this.service.checkOut(cookRes.orderNo)),
    map((checkOutResult) => OrderActions.processOrderSuccess({ data: checkOutResult })),
    catchError((error) => of(OrderActions.processOrderFailure({ error: error.message })))
  )
)

注意:需保证service方法返回的是冷Observable(如Angular HttpClient默认返回的类型),如果是热Observable会提前触发请求,无法实现串行效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 00:54:02