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

Node.js多HTTP请求数据整合:如何合并两个接口响应

问题:如何在Express中获取两个API的响应并一同返回?

我有一个API,触发时会发送两个HTTP Get请求,希望获取第一个Get请求的响应并存储到变量中,以便将其与第二个Get请求的响应一同返回。请问实现此需求的最佳方式是什么?

以下是我尝试的代码:

dummy.get("/api/dummy/memberProfileStats", isAuthenticated, (req, res) => {
  const userId = res.locals.user
  const memberProfileStatsURL = `/api/reports/users/${userId}/general`
  const memberLastLoginURL = `/api/users/${userId}/lastlogin`

  getRequest(memberLastLoginURL)
    .then(response => {
      let lastLoginTime = response.data.result
    })
    .catch(errorMessage => {
      console.log( 'Member Last Login API ERROR: ' + errorMessage)
      res.json(errorMessage)
    });

  getRequest(memberProfileStatsURL)
    .then(response => {
      let stats = response.data.result
      let pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
      let totalPoints = stats.totalPoints
      res.json({
        data: {
          totalPoints: stats.totalPoints,
          totalPointsRedeemed: stats.totalPointsRedeemed,
          availablePoints: (stats.totalPoints - stats.totalPointsRedeemed),
          totalSessionTime: secondsToHm(stats.totalSessionTime), //convert sessionTime seconds to hours
          loginsCount: stats.totalSessions,
          rank: rank(totalPoints, pointsRank),
          createdTime: stats.created,
          lastLoginTime: lastLoginTime,
        },
        result: response.data.httpStatusCode
      })
    })
    .catch(errorMessage => {
      res.json(errorMessage)
    });
})

但我遇到了**"lastLoginTime is not defined"**的错误。


解决方案

你碰到的问题根源有两个:

  1. 变量作用域限制:lastLoginTime是在第一个then回调的局部作用域里声明的,第二个请求的回调根本访问不到这个变量。
  2. 异步执行顺序问题:两个getRequest是并行发起的,第二个请求的回调可能在第一个请求完成前就执行了——就算作用域没问题,lastLoginTime也还没被赋值。

下面给你两种推荐的实现方案:

方案一:用Promise.all并行请求(效率优先)

如果两个API请求之间没有依赖关系,优先用Promise.all同时发起请求,等两者都返回结果后再统一处理,这样能最大化利用时间:

dummy.get("/api/dummy/memberProfileStats", isAuthenticated, async (req, res) => {
  try {
    const userId = res.locals.user
    const memberProfileStatsURL = `/api/reports/users/${userId}/general`
    const memberLastLoginURL = `/api/users/${userId}/lastlogin`

    // 同时发起两个请求,等待所有请求完成
    const [lastLoginRes, statsRes] = await Promise.all([
      getRequest(memberLastLoginURL),
      getRequest(memberProfileStatsURL)
    ])

    const lastLoginTime = lastLoginRes.data.result
    const stats = statsRes.data.result
    const pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
    const totalPoints = stats.totalPoints

    res.json({
      data: {
        totalPoints: stats.totalPoints,
        totalPointsRedeemed: stats.totalPointsRedeemed,
        availablePoints: stats.totalPoints - stats.totalPointsRedeemed,
        totalSessionTime: secondsToHm(stats.totalSessionTime),
        loginsCount: stats.totalSessions,
        rank: rank(totalPoints, pointsRank),
        createdTime: stats.created,
        lastLoginTime: lastLoginTime,
      },
      result: statsRes.data.httpStatusCode
    })
  } catch (error) {
    console.log('API 请求出错: ' + error)
    res.json(error)
  }
})

这里用async/await让代码更简洁易读,Promise.all会等待所有请求完成后再继续执行,同时统一处理所有错误,避免了原代码中可能出现的多次调用res.json的问题。

方案二:串行请求(适合有依赖的场景)

如果第二个请求需要依赖第一个请求的结果(虽然你的场景不需要,但可以作为参考),可以按顺序发起请求:

dummy.get("/api/dummy/memberProfileStats", isAuthenticated, (req, res) => {
  const userId = res.locals.user
  const memberProfileStatsURL = `/api/reports/users/${userId}/general`
  const memberLastLoginURL = `/api/users/${userId}/lastlogin`

  getRequest(memberLastLoginURL)
    .then(lastLoginRes => {
      const lastLoginTime = lastLoginRes.data.result
      // 第一个请求完成后,再发起第二个请求
      return getRequest(memberProfileStatsURL).then(statsRes => ({ lastLoginTime, statsRes }))
    })
    .then(({ lastLoginTime, statsRes }) => {
      const stats = statsRes.data.result
      const pointsRank = [150, 500, 1000, 2000, 3500, 5000, 5500]
      const totalPoints = stats.totalPoints

      res.json({
        data: {
          totalPoints: stats.totalPoints,
          totalPointsRedeemed: stats.totalPointsRedeemed,
          availablePoints: stats.totalPoints - stats.totalPointsRedeemed,
          totalSessionTime: secondsToHm(stats.totalSessionTime),
          loginsCount: stats.totalSessions,
          rank: rank(totalPoints, pointsRank),
          createdTime: stats.created,
          lastLoginTime: lastLoginTime,
        },
        result: statsRes.data.httpStatusCode
      })
    })
    .catch(error => {
      console.log('API 请求出错: ' + error)
      res.json(error)
    })
})

这种方式会先完成第一个请求,拿到lastLoginTime后再发起第二个请求,确保变量已经被正确赋值。

额外提醒

原代码中两个请求的错误处理是分开的,可能会导致重复发送响应(比如两个请求都出错时,会两次调用res.json,引发Express错误)。上面的两种方案都统一了错误处理逻辑,避免了这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 08:42:51