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

NGRX Effects链式API调用异常:无网络请求返回旧数据求助

NGRX Effects链式异步流程异常:getShippingMethods请求未触发,返回旧数据

问题概述

使用CommerceTools + NGRX处理结账地址切换流程时,出现以下异常:

  • 流程分为四步:重置配送地址→获取匹配配送方式→获取默认配送方式ID→设置默认配送方式,所有步骤依赖API调用
  • 触发第一步后,getShippingMethodsSuccess action已触发,但对应GET请求未出现在网络面板,导致使用旧配送方式ID调用API时CommerceTools返回错误
  • 部分场景(多次切换地址、延迟切换后快速操作)功能正常

核心原因分析

  1. GET请求浏览器缓存:getShippingMethods接口使用GET请求,URL仅包含cartId,切换地址后cartId未变,浏览器缓存了旧响应,导致新请求未实际发送,直接返回旧数据
  2. 状态一致性问题:getShippingMethodsSuccess未携带最新cart信息,后续流程从store获取的cart可能是旧版本,触发409版本冲突错误
  3. 竞态条件:快速操作时,异步流程的状态更新与action触发顺序不一致,导致数据不同步

修复方案

1. 禁用GET请求缓存

修改getShippingMethods方法,添加缓存控制头,强制浏览器不缓存响应:

import { HttpHeaders } from '@angular/common/http';

getShippingMethods(cart: Cart ) {
  const url = `${environment.commercetoolsURL}/${environment.commercetoolsProjectKey}/shipping-methods/matching-cart?cartId=${cart.id}`;
  const headers = new HttpHeaders({
    'Cache-Control': 'no-cache',
    Pragma: 'no-cache',
    Expires: '0'
  });
  return this.http.get(url, { headers }).pipe(map((data: any) => data.results));
}

2. 传递最新cart信息,避免依赖旧store状态

修改Action定义

在fromActions.ts中更新getShippingMethodsSuccess,携带最新cart:

export const getShippingMethodsSuccess = createAction(
  '[Cart] Get Shipping Methods Success',
  props<{ shippingMethods: ShippingMethod[], cart: Cart }>()
);

更新runGetShippingMethods$ Effect

触发成功action时传入最新cart:

runGetShippingMethods$ = createEffect(() =>
  this.actions$.pipe(
    ofType(fromActions.getShippingMethods),
    mergeMap(({ cart }) => this._addressService.getShippingMethods(cart).pipe(
      map((shippingMethods: ShippingMethod[]) => 
        fromActions.getShippingMethodsSuccess({ shippingMethods, cart })
      ),
      catchError((err) => of(fromActions.getShippingMethodsFailed({ error: err })))
    ))
  )
);

调整setDefaultShippingMethod$ Effect

直接使用action中的最新cart,不再从store获取:

setDefaultShippingMethod$ = createEffect(() =>
  this.actions$.pipe(
    ofType(fromActions.getShippingMethodsSuccess),
    mergeMap(({ shippingMethods, cart }) =>
      from(this._addressService.getDefaultShippingMethod(shippingMethods)).pipe(
        tap((defaultShippingMethod) => console.log(defaultShippingMethod)),
        mergeMap((shippingMethod: ShippingMethod) => [
          fromActions.updateOrderData({
            cart,
            actions: [
              {
                action: 'setShippingMethod',
                data: {
                  key: 'shippingMethod',
                  value: { id: shippingMethod.id, typeId: 'shipping-method' },
                },
              },
            ]
          }),
        ]),
        catchError((err) => {
          console.log(err);
          return of(fromActions.updateOrderDataFailed({ error: err }));
        })
      )
    )
  )
);

3. 修正409重试时的cart版本

在updateOrderData$ Effect中,重试时更新cart对象的version,确保后续流程使用最新版本:

catchError((err) => {
  if (err.status === 409) {
    console.log('%c---version mismatch retry update order---', 'background: red; color: white; padding: 3px; border-radius: 2px;');
    const newVersionNumber: number = err.error.errors[0].currentVersion;
    return of(fromActions.updateOrderData({
      cart: { ...payload.cart, version: newVersionNumber }, // 更新cart的version
      actions: payload.actions,
      version: newVersionNumber
    }));
  } else {
    return of(fromActions.updateOrderDataFailed({ error: err }));
  }
})

验证步骤

  1. 切换配送地址,查看网络面板确认getShippingMethods请求每次都被发送
  2. 检查getShippingMethodsSuccess返回的配送方式是否与新地址匹配
  3. 快速多次切换地址,确认流程无报错,CommerceTools端数据同步正确

内容的提问来源于stack exchange,提问作者rd.vdw

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 02:05:55