Google Maps距离矩阵API回调中变量赋值后仍为undefined的异步问题解决咨询
解决Google Distance Matrix异步操作导致的问题
你说得没错,这完全是异步操作的执行顺序问题——distance.matrix是一个基于回调的异步函数,它会在后台发送API请求,而你的代码里,回调函数之外的console.log(dist)和res.send("OK")会直接先运行,这时候dist还没被赋值,所以输出undefined;等API请求完成后,回调才会触发,给dist赋值并输出["320", "km"]。
要修复这个问题,核心是让后续操作(比如计算碳足迹、处理响应)必须等待异步请求完成后再执行,这里有两种常用的解决方案:
方案1:把后续逻辑放到回调函数内部
最直接的方式就是把所有依赖距离结果的代码,都移到distance.matrix的回调函数里,确保拿到结果后再执行:
app.get("/users", (req, res) => { const origins = [`${req.query.origin}`]; const destinations = [`${req.query.dest}`]; try { // 异步请求距离矩阵 distance.matrix(origins, destinations, (err, distances) => { if (err) { console.log(err); return res.status(404).send("Error"); } if (!distances) { return res.send("No distance calculated"); } // 拿到距离结果 const dist = distances.rows[0].elements[0].distance.text.split(" "); console.log(dist); // 在这里执行你需要的后续操作,比如计算碳足迹 const carbonEstimate = parseFloat(dist[0]) * 0.23; // 示例计算逻辑 // 所有操作完成后再发送响应 res.send({ status: "OK", carbonEstimate: `${carbonEstimate} kg CO2`, distance: `${dist[0]} ${dist[1]}` }); }); } catch(err) { console.log(err); res.send("ERROR"); } });
方案2:用Promise包装+async/await(更易读的写法)
如果觉得嵌套回调不够优雅,可以把distance.matrix包装成Promise,然后用async/await让异步代码看起来像同步代码:
首先封装一个Promise版本的距离矩阵函数:
// 把回调式的API包装成Promise const getDistanceMatrix = (origins, destinations) => { return new Promise((resolve, reject) => { distance.matrix(origins, destinations, (err, distances) => { if (err) reject(err); else resolve(distances); }); }); };
然后在路由里使用async/await:
// 给路由处理函数加上async关键字 app.get("/users", async (req, res) => { try { const origins = [`${req.query.origin}`]; const destinations = [`${req.query.dest}`]; // 等待异步请求完成,拿到结果 const distances = await getDistanceMatrix(origins, destinations); if (!distances) { return res.send("No distance calculated"); } const dist = distances.rows[0].elements[0].distance.text.split(" "); console.log(dist); // 执行后续操作,比如碳足迹计算 const carbonEstimate = parseFloat(dist[0]) * 0.23; // 发送最终响应 res.send({ status: "OK", carbonEstimate: `${carbonEstimate} kg CO2`, distance: `${dist[0]} ${dist[1]}` }); } catch(err) { console.log(err); res.status(500).send("ERROR"); } });
关键提醒
原来的代码里res.send("OK")写在回调外面,会在API请求完成前就发送响应,这不仅会导致拿不到距离结果,还可能因为后续回调里再操作res而报错——所以必须把响应逻辑放到异步操作完成之后。
内容的提问来源于stack exchange,提问作者Srijan
相关产品推荐
相关产品推荐

