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

求助:JavaScript嵌套函数返回距离值首次执行undefined,二次执行正常

解决Google Maps DirectionsService首次获取距离返回undefined的问题

嘿,我太懂这个坑了!你遇到的问题完全是因为Google Maps的DirectionsService.route()是异步操作导致的——这可是前端开发里新手常踩的经典陷阱😅

问题根源拆解

先看你代码的核心逻辑:你定义了全局变量Distance,然后在calcRoute()里调用directionsService.route()请求路线数据。但这个方法不会立刻返回结果,它会在后台发送请求,等Google服务器返回数据后才会触发回调函数,在回调里给Distance赋值。

而你大概率是在调用calcRoute()之后立刻去读取Distance——这时候异步请求还没完成,回调函数根本没执行,Distance自然还是初始的undefined。第二次执行时,第一次的异步请求已经完成,Distance被成功赋值,所以就能拿到正确值了。

举个更直观的简化版代码示例:

var directionsService = new google.maps.DirectionsService();
var Distance; 

function calcRoute() {
  var source = document.getElementById("txtSource").value;
  var destination = document.getElementById("txtDestination").value;

  var request = {
    origin: source,
    destination: destination,
    travelMode: google.maps.TravelMode.DRIVING
  };

  // 异步请求:这行代码立刻执行,但回调要等服务器响应才触发
  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      Distance = response.routes[0].legs[0].distance.value;
    }
  });
}

// 调用后立刻读Distance,此时回调还没执行!
calcRoute();
console.log(Distance); // 第一次输出undefined,第二次可能有值

靠谱的解决方案

解决异步问题的核心思路是:不要在异步操作完成前试图获取结果,必须等回调触发后再处理数据。这里给你两种常用的写法:

方案1:用回调函数传递结果

把需要用到距离的逻辑直接放到回调里,或者传入一个自定义回调函数,让异步结果触发后再执行你的业务逻辑:

var directionsService = new google.maps.DirectionsService();

function calcRoute(callback) {
  var source = document.getElementById("txtSource").value;
  var destination = document.getElementById("txtDestination").value;

  var request = {
    origin: source,
    destination: destination,
    travelMode: google.maps.TravelMode.DRIVING
  };

  directionsService.route(request, function(response, status) {
    if (status == google.maps.DirectionsStatus.OK) {
      var distance = response.routes[0].legs[0].distance.value;
      callback(null, distance); // 成功时把结果传给回调
    } else {
      callback(new Error(`获取路线失败:${status}`), null); // 失败时传递错误
    }
  });
}

// 调用方式:只有当异步请求完成后,才会执行这里的逻辑
calcRoute(function(err, distance) {
  if (err) {
    console.error(err);
    return;
  }
  console.log("计算得到的距离:", distance);
  // 在这里写你需要用距离做的事情,比如更新页面、计算费用等
});

方案2:用Promise封装(更现代的写法)

把异步操作封装成Promise,这样可以用then()链式调用,或者更简洁的async/await语法:

var directionsService = new google.maps.DirectionsService();

function calcRoute() {
  return new Promise((resolve, reject) => {
    var source = document.getElementById("txtSource").value;
    var destination = document.getElementById("txtDestination").value;

    var request = {
      origin: source,
      destination: destination,
      travelMode: google.maps.TravelMode.DRIVING
    };

    directionsService.route(request, function(response, status) {
      if (status == google.maps.DirectionsStatus.OK) {
        var distance = response.routes[0].legs[0].distance.value;
        resolve(distance); // 成功时返回结果
      } else {
        reject(new Error(`获取路线失败:${status}`)); // 失败时抛出错误
      }
    });
  });
}

// 方式一:用then()链式调用
calcRoute()
  .then(distance => {
    console.log("计算得到的距离:", distance);
    // 处理距离相关逻辑
  })
  .catch(err => console.error(err));

// 方式二:用async/await(需要在async函数内使用)
async function getDistance() {
  try {
    const distance = await calcRoute();
    console.log("计算得到的距离:", distance);
    // 处理距离相关逻辑
  } catch (err) {
    console.error(err);
  }
}

getDistance();

最后提醒

尽量不要用全局变量存储异步操作的结果,这种写法很容易出现时序问题,而且代码可读性差。用回调、Promise或者async/await才是处理异步逻辑的标准方式,能让你的代码更可靠、更易维护~

内容的提问来源于stack exchange,提问作者Ranjit Singh Shekhawat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:45:38