TypeScript异步函数返回Promise{<pending>}而非预期值的问题
问题与解决方案:异步函数调用导致的Promise pending及返回值错误
在Express框架的TypeScript代码中,fetchCellId调用异步函数getCellId请求第三方POST接口时,遇到两个核心问题:
- 直接赋值
results = getCellId(...)得到的是Promise{<pending>},使用then回调也无法同步获取结果; - 用
await关键字时,得到的是庞大的ServerResponse对象,而非预期的第三方接口返回数据。
原代码片段
const fetchCellId = async (req: Request, res: Response,next: NextFunction)=>{ const cellId = req.query.cellId as string; let results; try { results = getCellId(req, res, next); results.then(data =>{ return data; }); console.log('look78'); console.log(results); await redisClient.set(cellId, JSON.stringify(results), { EX: 180, NX: true, }); console.log('look 54') res.send({ fromCache: false, data: results, }); console.log('look 56') }catch (error) { console.error(error); res.status(404).send("Data unavailable"); } } const getCellId = async (req: Request, res: Response, next: NextFunction) => { console.log('look 10'); let id: string = req.query.cellId as string; console.log(id); let cid = id.substring(0, 5); let lac = id.substring(12,16); let mcc = id.substring(6, 9); let mnc = id[10]; console.log(cid); console.log(lac); console.log(mcc); console.log(mnc); let response: AxiosResponse = await axios.post(`https://eu1.unwiredlabs.com/v2/process.php`, { 'token': 'pk.ccd04*****######6', 'radio': 'lte', 'mcc': mcc, 'mnc': mnc, 'cells': [{ 'lac': lac, 'cid': cid }] }); const cellIdRes = await res.status(200).json({ "lng": response.data.lon, "lat": response.data.lat, "acc": response.data.accuracy }); console.log(cellIdRes); return cellIdRes; };
问题原因分析
- Promise pending问题:异步函数调用后必须用
await等待Promise决议完成,直接赋值或仅用then回调无法阻塞后续代码执行,导致后续使用results时仍处于pending状态。 - 返回ServerResponse问题:
getCellId中调用的res.status(200).json(...)方法返回的是Express的ServerResponse对象,而非第三方接口的解析数据。错误地将该响应对象作为函数返回值,导致await getCellId(...)拿到的是res对象而非预期数据。
修正后的代码
1. 修正getCellId函数(职责分离:仅处理数据获取与转换)
const getCellId = async (req: Request, res: Response, next: NextFunction) => { console.log('look 10'); const id: string = req.query.cellId as string; console.log(id); const cid = id.substring(0, 5); const lac = id.substring(12,16); const mcc = id.substring(6, 9); const mnc = id[10]; console.log(cid, lac, mcc, mnc); const response: AxiosResponse = await axios.post(`https://eu1.unwiredlabs.com/v2/process.php`, { 'token': 'pk.ccd04*****######6', 'radio': 'lte', 'mcc': mcc, 'mnc': mnc, 'cells': [{ 'lac': lac, 'cid': cid }] }); // 直接返回处理后的第三方接口数据,将响应发送逻辑交给上层函数 return { "lng": response.data.lon, "lat": response.data.lat, "acc": response.data.accuracy }; };
2. 修正fetchCellId函数(用await等待异步结果)
const fetchCellId = async (req: Request, res: Response, next: NextFunction) => { const cellId = req.query.cellId as string; try { // 用await等待异步函数完成,获取实际数据 const results = await getCellId(req, res, next); console.log('look78'); console.log(results); // 存入Redis时使用实际数据而非Promise await redisClient.set(cellId, JSON.stringify(results), { EX: 180, NX: true, }); console.log('look 54'); // 统一在该函数中发送响应 res.send({ fromCache: false, data: results, }); console.log('look 56'); } catch (error) { console.error(error); res.status(404).send("Data unavailable"); } };
关键修正点
- 异步函数调用必须搭配
await才能获取最终结果,否则仅能拿到未决议的Promise; - 拆分函数职责:数据处理(
getCellId)与HTTP响应发送(fetchCellId)分离,避免混淆返回值类型; - 确保每个函数只完成单一任务,提升代码可维护性与可读性。
内容的提问来源于stack exchange,提问作者SUNDARAM SRIVASTAVA
相关产品推荐
相关产品推荐

