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

嵌套异步请求最佳实践:Next.js购物车数据获取代码优化问询

购物车数据获取代码优化建议请求

我正在用Axios调用第三方API获取用户购物车数据,接口返回产品ID列表和对应数量,之后我会遍历这些ID获取完整产品信息。目前代码能正常运行,但我对Promise不太熟悉,想请教代码优化方向:是否应该拆分第二个then?当前写法是否符合最佳实践?补充:我用的是Next.js,这个函数会在getStaticProps里调用。

export const getCartProducts = async () => {
  const data = await axios
    // get most recent cart of user
    .get('https://example.com/api/carts', {
      params: {
        display: 'full',
        output_format: 'JSON',
        'filter[id_customer]': '[0]',
        sort: '[id_DESC]',
        limit: '1',
      },
      headers: {
        Authorization: 'Basic ' + btoa(process.env.API_AUTH + ':'),
        Accept: 'application/json',
      },
    })
    .then((cartResponse) => {
      const cart = cartResponse.data.carts[0];

      // return product ids and quantity
      const cartMeta: TCartItem[] = cart.associations.cart_rows.map(
        (item: any) => {
          const { id_product, quantity } = item;
          return {
            id: id_product.toString(),
            quantity,
          };
        }
      );

      return cartMeta;
    })
    .then(async (cartMeta: TCartItem[]) => {
      const items: (TCartProduct | undefined)[] | void = await axios
        // fetch product data for each id
        .all(cartMeta.map((item: TCartItem) => getProductById(item.id)))
        .then((products) =>
          products.map((product: TProduct | null) => {
            if (product) {
              const productCartMeta = cartMeta.find(
                (meta) => meta.id === product?.id
              ) as TCartItem;

              // return data needed for product display on cart page
              return {
                ...product,
                quantity: productCartMeta?.quantity ?? 0,
              };
            }

            return;
          })
        )
        .catch((error) => handleError(error));

      return items;
    })
    .catch((error) => handleError(error));
  
  // called in Next.js `getStaticProps` so needs to default to null
  return data ?? null;
};

优化建议:统一用async/await替代混合写法

你的代码同时混用了await和Promise链式then,在async函数里更推荐统一使用async/await,这种写法比链式then更易读,也更容易拆分逻辑,符合现代JS最佳实践。

1. 拆分第二个then是合理的,甚至可以拆得更细

把每个独立逻辑拆成线性步骤,或者抽成小函数,让代码职责更单一,调试和维护起来更方便。比如可以拆成这几步:

  • 获取购物车基础数据
  • 提取产品ID与数量的映射关系
  • 批量获取所有产品详情
  • 合并产品详情和数量信息

2. 优化后的代码示例

export const getCartProducts = async () => {
  try {
    // 1. 获取用户最新购物车数据
    const cartResponse = await axios.get('https://example.com/api/carts', {
      params: {
        display: 'full',
        output_format: 'JSON',
        'filter[id_customer]': '[0]',
        sort: '[id_DESC]',
        limit: '1',
      },
      headers: {
        Authorization: 'Basic ' + btoa(process.env.API_AUTH + ':'),
        Accept: 'application/json',
      },
    });

    const cart = cartResponse.data.carts[0];
    // 处理空购物车或无产品的边界情况
    if (!cart?.associations?.cart_rows?.length) {
      return null;
    }

    // 2. 用对象映射存储ID与数量,替代数组find(性能从O(n)优化到O(1))
    const cartQuantityMap = cart.associations.cart_rows.reduce((map, item) => {
      const productId = item.id_product.toString();
      map[productId] = item.quantity;
      return map;
    }, {} as Record<string, number>);

    // 3. 批量获取所有产品详情
    const productIds = Object.keys(cartQuantityMap);
    const products = await axios.all(productIds.map(id => getProductById(id)));

    // 4. 合并产品信息与数量,过滤无效产品
    const items = products
      .filter(product => product !== null)
      .map(product => ({
        ...product,
        quantity: cartQuantityMap[product.id] ?? 0,
      }));

    return items;
  } catch (error) {
    handleError(error);
    // 符合getStaticProps要求,出错时返回null
    return null;
  }
};

关键优化点说明

  • 统一async/await风格:避免回调嵌套,代码线性化,可读性大幅提升
  • 性能优化:用对象映射替代数组find,批量处理产品时匹配效率更高
  • 边界处理:提前判断空购物车情况,避免后续逻辑报错
  • 集中错误处理:所有逻辑放在一个try/catch中,无需多个catch分支,更简洁
  • 过滤无效数据:直接剔除getProductById返回的null值,避免数组中出现undefined

关于是否拆分第二个then的结论

当前的链式then写法虽然能运行,但在async函数里拆分并改用await是更优的选择。拆分后每个步骤职责单一,代码结构更清晰,也更贴合Next.js中getStaticProps常用的线性await代码风格,后续维护和调试都会更轻松。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 18:57:38