如何用Node.js与Express将两个玩家API请求合并为单个端点?
合并两个Express接口返回组合JSON数据的实现方案
要实现把getPlayerAge和getPlayerRank的结果合并到单个接口返回,核心是并行调用两个异步获取数据的方法,再把结果组合成一个JSON返回。下面是具体的实现步骤和代码修改:
1. 新增合并接口的路由处理
在你的PlayerRoutes代码中,添加一个新的GET路由/getBothPlayerAgeAndRank,逻辑如下:
- 先校验请求参数
player是否存在,和原有接口保持一致 - 用
Promise.all并行调用两个获取数据的方法(比串行调用效率更高) - 把两个接口的结果组合成一个对象返回
- 统一处理错误和未找到的情况
修改后的完整代码如下:
import * as Promise from 'bluebird'; import { Request, Response, Router } from 'express'; import * as https from 'https'; import * as http from 'http'; import * as apicache from 'apicache'; import { PlayerModule } from '../modules'; const router = Router(); const cache = apicache.middleware; // 原有getPlayerAge接口 router.get('/getPlayerAge', (req: Request, res: Response, next: () => void) => { let playerName: string; if (!req.query.player) { res.json([]); next(); } else { playerName = req.query.player; PlayerModule.getPlayerAge(playerName) .then((results) => { if (results.length > 0) { res.json(results[0]); } else { res.sendStatus(404); } }) .catch((reason) => { //console.error(reason); res.sendStatus(500); }) .finally(next); } }); // 原有getPlayerRank接口 router.get('/getPlayerRank', (req: Request, res: Response, next: () => void) => { let playerName: string; if (!req.query.player) { res.json([]); next(); } else { playerName = req.query.player; PlayerModule.getPlayerRank(playerName) .then((results) => { if (results.length > 0) { res.json(results[0]); } else { res.sendStatus(404); } }) .catch((reason) => { //console.error(reason); res.sendStatus(500); }) .finally(next); } }); // 新增的合并接口 router.get('/getBothPlayerAgeAndRank', (req: Request, res: Response, next: () => void) => { const playerName = req.query.player as string; // 参数校验 if (!playerName) { res.json({}); next(); return; } // 并行调用两个异步方法 Promise.all([ PlayerModule.getPlayerAge(playerName), PlayerModule.getPlayerRank(playerName) ]) .then(([ageResults, rankResults]) => { // 方案1:两个数据都存在才返回,否则404 if (ageResults.length > 0 && rankResults.length > 0) { res.json({ playerAge: ageResults[0], playerRank: rankResults[0] }); } else { res.sendStatus(404); } // 方案2:允许返回部分数据(比如某一个接口没找到,另一个返回) // res.json({ // playerAge: ageResults.length > 0 ? ageResults[0] : null, // playerRank: rankResults.length > 0 ? rankResults[0] : null // }); }) .catch((reason) => { // 捕获任意一个请求的错误,返回500 //console.error(reason); res.sendStatus(500); }) .finally(next); }); export const PlayerRoutes = router;
2. 关键逻辑说明
- 并行调用:用
Promise.all同时发起两个数据请求,相比串行调用(先查年龄再查排名)能减少整体响应时间 - 结果组合:解构
Promise.all返回的数组,把两个结果放到同一个JSON对象的不同字段中(比如playerAge和playerRank) - 错误处理:只要其中一个请求抛出错误,就会进入
catch块返回500;如果需要单独处理每个请求的错误,可以把每个方法包装成catch返回默认值,比如:Promise.all([ PlayerModule.getPlayerAge(playerName).catch(() => []), PlayerModule.getPlayerRank(playerName).catch(() => []) ]) - 参数校验:和原有接口保持一致,确保
player参数存在
3. Angular前端调用示例
在Angular的服务中,可以这样调用新接口:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; interface PlayerCombinedData { playerAge: any; // 替换成实际的类型 playerRank: any; // 替换成实际的类型 } @Injectable({ providedIn: 'root' }) export class PlayerService { constructor(private http: HttpClient) {} getBothPlayerAgeAndRank(playerName: string): Observable<PlayerCombinedData> { return this.http.get<PlayerCombinedData>(`/api/getBothPlayerAgeAndRank?player=${playerName}`); } }
这样就能在前端获取到包含年龄和排名的组合数据了。
内容的提问来源于stack exchange,提问作者HenryAD
相关产品推荐
相关产品推荐

